@muloka/figma-console-mcp 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/core/websocket-connector.d.ts +2 -1
- package/dist/core/websocket-connector.d.ts.map +1 -1
- package/dist/core/websocket-connector.js +17 -2
- package/dist/core/websocket-connector.js.map +1 -1
- package/dist/core/websocket-server.d.ts +8 -1
- package/dist/core/websocket-server.d.ts.map +1 -1
- package/dist/core/websocket-server.js +19 -3
- package/dist/core/websocket-server.js.map +1 -1
- package/dist/core/write-tools.d.ts +3 -1
- package/dist/core/write-tools.d.ts.map +1 -1
- package/dist/core/write-tools.js +98 -23
- package/dist/core/write-tools.js.map +1 -1
- package/dist/local.d.ts +2 -1
- package/dist/local.d.ts.map +1 -1
- package/dist/local.js +5 -4
- package/dist/local.js.map +1 -1
- package/figma-desktop-bridge/code.js +57 -27
- package/figma-desktop-bridge/ui.html +10 -2
- package/package.json +1 -1
- package/dist/apps/design-system-dashboard/mcp-app.html +0 -521
- package/dist/apps/token-browser/mcp-app.html +0 -410
- package/dist/cloudflare/apps/design-system-dashboard/scoring/accessibility.js +0 -277
- package/dist/cloudflare/apps/design-system-dashboard/scoring/component-metadata.js +0 -357
- package/dist/cloudflare/apps/design-system-dashboard/scoring/consistency.js +0 -341
- package/dist/cloudflare/apps/design-system-dashboard/scoring/coverage.js +0 -230
- package/dist/cloudflare/apps/design-system-dashboard/scoring/engine.js +0 -92
- package/dist/cloudflare/apps/design-system-dashboard/scoring/naming-semantics.js +0 -308
- package/dist/cloudflare/apps/design-system-dashboard/scoring/token-architecture.js +0 -349
- package/dist/cloudflare/apps/design-system-dashboard/scoring/types.js +0 -40
- package/dist/cloudflare/apps/design-system-dashboard/server.js +0 -159
- package/dist/cloudflare/apps/token-browser/server.js +0 -136
- package/dist/cloudflare/browser-manager.js +0 -157
- package/dist/cloudflare/core/accessibility-tools.js +0 -361
- package/dist/cloudflare/core/annotation-tools.js +0 -230
- package/dist/cloudflare/core/cloud-websocket-connector.js +0 -419
- package/dist/cloudflare/core/cloud-websocket-relay.js +0 -198
- package/dist/cloudflare/core/comment-tools.js +0 -292
- package/dist/cloudflare/core/config.js +0 -153
- package/dist/cloudflare/core/console-monitor.js +0 -427
- package/dist/cloudflare/core/deep-component-tools.js +0 -128
- package/dist/cloudflare/core/design-code-tools.js +0 -2793
- package/dist/cloudflare/core/design-system-manifest.js +0 -265
- package/dist/cloudflare/core/design-system-tools.js +0 -882
- package/dist/cloudflare/core/diagnose-tool.js +0 -100
- package/dist/cloudflare/core/diff/changelog-formatter.js +0 -275
- package/dist/cloudflare/core/diff/diff-engine.js +0 -334
- package/dist/cloudflare/core/diff/property-compare.js +0 -36
- package/dist/cloudflare/core/diff/version-cache.js +0 -74
- package/dist/cloudflare/core/enrichment/enrichment-service.js +0 -374
- package/dist/cloudflare/core/enrichment/index.js +0 -7
- package/dist/cloudflare/core/enrichment/relationship-mapper.js +0 -351
- package/dist/cloudflare/core/enrichment/style-resolver.js +0 -346
- package/dist/cloudflare/core/figjam-tools.js +0 -547
- package/dist/cloudflare/core/figma-api.js +0 -509
- package/dist/cloudflare/core/figma-connector.js +0 -7
- package/dist/cloudflare/core/figma-reconstruction-spec.js +0 -402
- package/dist/cloudflare/core/figma-style-extractor.js +0 -311
- package/dist/cloudflare/core/figma-tools.js +0 -3353
- package/dist/cloudflare/core/identity.js +0 -96
- package/dist/cloudflare/core/library-tools.js +0 -580
- package/dist/cloudflare/core/logger.js +0 -53
- package/dist/cloudflare/core/port-discovery.js +0 -935
- package/dist/cloudflare/core/resolve-package-root.js +0 -11
- package/dist/cloudflare/core/slides-tools.js +0 -714
- package/dist/cloudflare/core/slot-tools.js +0 -334
- package/dist/cloudflare/core/snippet-injector.js +0 -96
- package/dist/cloudflare/core/tokens/alias-resolver.js +0 -205
- package/dist/cloudflare/core/tokens/config.js +0 -294
- package/dist/cloudflare/core/tokens/dialect.js +0 -232
- package/dist/cloudflare/core/tokens/figma-converter.js +0 -323
- package/dist/cloudflare/core/tokens/formatters/css-vars.js +0 -338
- package/dist/cloudflare/core/tokens/formatters/dtcg.js +0 -376
- package/dist/cloudflare/core/tokens/formatters/index.js +0 -45
- package/dist/cloudflare/core/tokens/formatters/json.js +0 -205
- package/dist/cloudflare/core/tokens/formatters/less.js +0 -4
- package/dist/cloudflare/core/tokens/formatters/scss.js +0 -258
- package/dist/cloudflare/core/tokens/formatters/stubs.js +0 -13
- package/dist/cloudflare/core/tokens/formatters/style-dictionary-v3.js +0 -213
- package/dist/cloudflare/core/tokens/formatters/tailwind-v3.js +0 -237
- package/dist/cloudflare/core/tokens/formatters/tailwind-v4.js +0 -335
- package/dist/cloudflare/core/tokens/formatters/tokens-studio.js +0 -256
- package/dist/cloudflare/core/tokens/formatters/ts-module.js +0 -198
- package/dist/cloudflare/core/tokens/index.js +0 -16
- package/dist/cloudflare/core/tokens/parsers/css-vars.js +0 -4
- package/dist/cloudflare/core/tokens/parsers/dtcg.js +0 -280
- package/dist/cloudflare/core/tokens/parsers/index.js +0 -138
- package/dist/cloudflare/core/tokens/parsers/json.js +0 -7
- package/dist/cloudflare/core/tokens/parsers/scss.js +0 -4
- package/dist/cloudflare/core/tokens/parsers/stubs.js +0 -20
- package/dist/cloudflare/core/tokens/parsers/style-dictionary-v3.js +0 -4
- package/dist/cloudflare/core/tokens/parsers/tailwind-v3.js +0 -4
- package/dist/cloudflare/core/tokens/parsers/tailwind-v4.js +0 -4
- package/dist/cloudflare/core/tokens/parsers/tokens-studio.js +0 -4
- package/dist/cloudflare/core/tokens/schemas.js +0 -152
- package/dist/cloudflare/core/tokens/transforms/color.js +0 -12
- package/dist/cloudflare/core/tokens/transforms/index.js +0 -29
- package/dist/cloudflare/core/tokens/transforms/size.js +0 -7
- package/dist/cloudflare/core/tokens/types.js +0 -18
- package/dist/cloudflare/core/tokens-tools.js +0 -1788
- package/dist/cloudflare/core/types/design-code.js +0 -4
- package/dist/cloudflare/core/types/enriched.js +0 -5
- package/dist/cloudflare/core/types/index.js +0 -4
- package/dist/cloudflare/core/variable-resolver.js +0 -85
- package/dist/cloudflare/core/version-tools.js +0 -1199
- package/dist/cloudflare/core/websocket-connector.js +0 -436
- package/dist/cloudflare/core/websocket-server.js +0 -1009
- package/dist/cloudflare/core/write-tools.js +0 -2506
- package/dist/cloudflare/index.js +0 -3010
|
@@ -1,374 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enrichment Service
|
|
3
|
-
* Coordinates enrichment of Figma API responses
|
|
4
|
-
*/
|
|
5
|
-
import { StyleValueResolver } from "./style-resolver.js";
|
|
6
|
-
import { RelationshipMapper } from "./relationship-mapper.js";
|
|
7
|
-
export class EnrichmentService {
|
|
8
|
-
constructor(logger) {
|
|
9
|
-
// Caches
|
|
10
|
-
this.fileDataCache = new Map();
|
|
11
|
-
this.lastEnrichmentTime = new Map();
|
|
12
|
-
this.CACHE_TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
13
|
-
this.logger = logger;
|
|
14
|
-
this.styleResolver = new StyleValueResolver(logger);
|
|
15
|
-
this.relationshipMapper = new RelationshipMapper(logger);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Enrich styles response
|
|
19
|
-
*/
|
|
20
|
-
async enrichStyles(styles, fileKey, options = {}, fileData) {
|
|
21
|
-
if (!options.enrich) {
|
|
22
|
-
return styles; // Return as-is if enrichment not requested
|
|
23
|
-
}
|
|
24
|
-
this.logger.info({ fileKey, count: styles.length }, "Enriching styles");
|
|
25
|
-
try {
|
|
26
|
-
// Get file data for relationships (use provided data if available)
|
|
27
|
-
const data = fileData || await this.getFileDataForEnrichment(fileKey);
|
|
28
|
-
const variables = this.extractVariablesMap(data);
|
|
29
|
-
// Build relationships if requested
|
|
30
|
-
if (options.include_usage) {
|
|
31
|
-
await this.relationshipMapper.buildRelationships(data);
|
|
32
|
-
}
|
|
33
|
-
const enrichedStyles = [];
|
|
34
|
-
for (const style of styles) {
|
|
35
|
-
const enriched = {
|
|
36
|
-
...style,
|
|
37
|
-
};
|
|
38
|
-
// Resolve value and variable reference
|
|
39
|
-
if (options.include_exports !== false) {
|
|
40
|
-
const { value, variableRef } = await this.styleResolver.resolveStyleValue(style, variables, options.max_depth);
|
|
41
|
-
enriched.resolved_value = value;
|
|
42
|
-
enriched.variable_reference = variableRef;
|
|
43
|
-
// Generate export formats
|
|
44
|
-
if (value && options.export_formats) {
|
|
45
|
-
enriched.export_formats = this.styleResolver.generateExportFormats(style.name, value, style.style_type, options.export_formats);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
// Add usage information
|
|
49
|
-
if (options.include_usage) {
|
|
50
|
-
const styleId = style.node_id || style.key || style.id;
|
|
51
|
-
enriched.used_in_components =
|
|
52
|
-
this.relationshipMapper.getComponentsByStyle(styleId);
|
|
53
|
-
enriched.usage_count =
|
|
54
|
-
this.relationshipMapper.getStyleUsageCount(styleId);
|
|
55
|
-
}
|
|
56
|
-
enrichedStyles.push(enriched);
|
|
57
|
-
}
|
|
58
|
-
this.logger.info({ enrichedCount: enrichedStyles.length }, "Styles enrichment complete");
|
|
59
|
-
return enrichedStyles;
|
|
60
|
-
}
|
|
61
|
-
catch (error) {
|
|
62
|
-
this.logger.error({ error }, "Failed to enrich styles");
|
|
63
|
-
return styles; // Return original on error
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Enrich variables response
|
|
68
|
-
*/
|
|
69
|
-
async enrichVariables(variables, fileKey, options = {}, fileData) {
|
|
70
|
-
if (!options.enrich) {
|
|
71
|
-
return variables;
|
|
72
|
-
}
|
|
73
|
-
this.logger.info({ fileKey, count: variables.length }, "Enriching variables");
|
|
74
|
-
try {
|
|
75
|
-
const data = fileData || await this.getFileDataForEnrichment(fileKey);
|
|
76
|
-
const variablesMap = this.extractVariablesMap(data);
|
|
77
|
-
// Build relationships if requested
|
|
78
|
-
if (options.include_usage) {
|
|
79
|
-
await this.relationshipMapper.buildRelationships(data);
|
|
80
|
-
}
|
|
81
|
-
const enrichedVars = [];
|
|
82
|
-
for (const variable of variables) {
|
|
83
|
-
const enriched = {
|
|
84
|
-
...variable,
|
|
85
|
-
};
|
|
86
|
-
// Resolve values for all modes — each mode must resolve ITS OWN
|
|
87
|
-
// value, so the modeId is threaded through the resolver (which
|
|
88
|
-
// also keys its cache per mode).
|
|
89
|
-
if (options.include_exports !== false) {
|
|
90
|
-
const resolved_values = {};
|
|
91
|
-
for (const modeId of Object.keys(variable.valuesByMode || {})) {
|
|
92
|
-
const resolvedValue = await this.styleResolver.resolveVariableValue(variable, variablesMap, options.max_depth, 0, modeId);
|
|
93
|
-
resolved_values[modeId] = resolvedValue;
|
|
94
|
-
}
|
|
95
|
-
enriched.resolved_values = resolved_values;
|
|
96
|
-
// Generate export formats using first mode. Guard only against
|
|
97
|
-
// null/undefined — legitimate falsy values (0, false, "") must
|
|
98
|
-
// still produce export formats.
|
|
99
|
-
const firstModeValue = Object.values(resolved_values)[0];
|
|
100
|
-
if (firstModeValue !== null &&
|
|
101
|
-
firstModeValue !== undefined &&
|
|
102
|
-
options.export_formats) {
|
|
103
|
-
enriched.export_formats = this.styleResolver.generateExportFormats(variable.name, firstModeValue, variable.resolvedType, options.export_formats);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Add usage information
|
|
107
|
-
if (options.include_usage) {
|
|
108
|
-
enriched.used_in_styles =
|
|
109
|
-
this.relationshipMapper.getStylesByVariable(variable.id);
|
|
110
|
-
enriched.used_in_components =
|
|
111
|
-
this.relationshipMapper.getComponentsByVariable(variable.id);
|
|
112
|
-
enriched.usage_count =
|
|
113
|
-
this.relationshipMapper.getVariableUsageCount(variable.id);
|
|
114
|
-
}
|
|
115
|
-
// Add dependencies
|
|
116
|
-
if (options.include_dependencies) {
|
|
117
|
-
enriched.dependencies =
|
|
118
|
-
this.relationshipMapper.getVariableDependencies(variable.id);
|
|
119
|
-
}
|
|
120
|
-
enrichedVars.push(enriched);
|
|
121
|
-
}
|
|
122
|
-
this.logger.info({ enrichedCount: enrichedVars.length }, "Variables enrichment complete");
|
|
123
|
-
return enrichedVars;
|
|
124
|
-
}
|
|
125
|
-
catch (error) {
|
|
126
|
-
this.logger.error({ error }, "Failed to enrich variables");
|
|
127
|
-
return variables;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Enrich component response
|
|
132
|
-
*/
|
|
133
|
-
async enrichComponent(component, fileKey, options = {}, fileData) {
|
|
134
|
-
if (!options.enrich) {
|
|
135
|
-
return component;
|
|
136
|
-
}
|
|
137
|
-
this.logger.info({ fileKey, componentId: component.id }, "Enriching component");
|
|
138
|
-
try {
|
|
139
|
-
const enriched = {
|
|
140
|
-
...component,
|
|
141
|
-
};
|
|
142
|
-
const data = fileData || await this.getFileDataForEnrichment(fileKey);
|
|
143
|
-
// Build relationships
|
|
144
|
-
await this.relationshipMapper.buildRelationships(data);
|
|
145
|
-
// Extract styles used
|
|
146
|
-
if (component.styles) {
|
|
147
|
-
const stylesUsed = [];
|
|
148
|
-
for (const [prop, styleId] of Object.entries(component.styles)) {
|
|
149
|
-
const style = data.styles?.[styleId];
|
|
150
|
-
if (style) {
|
|
151
|
-
stylesUsed.push({
|
|
152
|
-
style_id: styleId,
|
|
153
|
-
style_name: style.name,
|
|
154
|
-
style_type: style.style_type,
|
|
155
|
-
property: prop,
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
enriched.styles_used = stylesUsed;
|
|
160
|
-
}
|
|
161
|
-
// Extract variables used and detect hardcoded values by walking the node tree
|
|
162
|
-
const varsUsed = [];
|
|
163
|
-
const hardcodedValues = [];
|
|
164
|
-
const variables = this.extractVariablesMap(data);
|
|
165
|
-
// Walk node tree to find boundVariables and hardcoded values
|
|
166
|
-
const walkForTokens = (node, path = "") => {
|
|
167
|
-
if (!node)
|
|
168
|
-
return;
|
|
169
|
-
const nodePath = path ? `${path} > ${node.name || node.id}` : (node.name || node.id);
|
|
170
|
-
const bv = node.boundVariables || {};
|
|
171
|
-
// Check fills
|
|
172
|
-
if (node.fills && Array.isArray(node.fills)) {
|
|
173
|
-
for (let i = 0; i < node.fills.length; i++) {
|
|
174
|
-
const fill = node.fills[i];
|
|
175
|
-
if (fill.type === "SOLID" && fill.visible !== false) {
|
|
176
|
-
const fillBv = bv.fills;
|
|
177
|
-
if (fillBv && (Array.isArray(fillBv) ? fillBv[i] : fillBv)) {
|
|
178
|
-
const varRef = Array.isArray(fillBv) ? fillBv[i] : fillBv;
|
|
179
|
-
if (varRef?.id) {
|
|
180
|
-
const varInfo = variables.get(varRef.id);
|
|
181
|
-
varsUsed.push({
|
|
182
|
-
variableId: varRef.id,
|
|
183
|
-
variableName: varInfo?.name || varRef.id,
|
|
184
|
-
property: "fill",
|
|
185
|
-
nodePath,
|
|
186
|
-
});
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
else {
|
|
190
|
-
// Hardcoded fill
|
|
191
|
-
const c = fill.color;
|
|
192
|
-
if (c) {
|
|
193
|
-
hardcodedValues.push({
|
|
194
|
-
property: "fill",
|
|
195
|
-
value: `rgb(${Math.round(c.r * 255)}, ${Math.round(c.g * 255)}, ${Math.round(c.b * 255)})`,
|
|
196
|
-
nodePath,
|
|
197
|
-
});
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
// Check strokes
|
|
204
|
-
if (node.strokes && Array.isArray(node.strokes)) {
|
|
205
|
-
for (let i = 0; i < node.strokes.length; i++) {
|
|
206
|
-
const stroke = node.strokes[i];
|
|
207
|
-
if (stroke.type === "SOLID" && stroke.visible !== false) {
|
|
208
|
-
const strokeBv = bv.strokes;
|
|
209
|
-
if (strokeBv && (Array.isArray(strokeBv) ? strokeBv[i] : strokeBv)) {
|
|
210
|
-
const varRef = Array.isArray(strokeBv) ? strokeBv[i] : strokeBv;
|
|
211
|
-
if (varRef?.id) {
|
|
212
|
-
const varInfo = variables.get(varRef.id);
|
|
213
|
-
varsUsed.push({
|
|
214
|
-
variableId: varRef.id,
|
|
215
|
-
variableName: varInfo?.name || varRef.id,
|
|
216
|
-
property: "stroke",
|
|
217
|
-
nodePath,
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
const c = stroke.color;
|
|
223
|
-
if (c) {
|
|
224
|
-
hardcodedValues.push({
|
|
225
|
-
property: "stroke",
|
|
226
|
-
value: `rgb(${Math.round(c.r * 255)}, ${Math.round(c.g * 255)}, ${Math.round(c.b * 255)})`,
|
|
227
|
-
nodePath,
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
// Check spacing/sizing tokens
|
|
235
|
-
const spacingProps = ["itemSpacing", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "cornerRadius"];
|
|
236
|
-
for (const prop of spacingProps) {
|
|
237
|
-
if (node[prop] !== undefined && node[prop] !== 0) {
|
|
238
|
-
if (bv[prop]?.id) {
|
|
239
|
-
const varInfo = variables.get(bv[prop].id);
|
|
240
|
-
varsUsed.push({
|
|
241
|
-
variableId: bv[prop].id,
|
|
242
|
-
variableName: varInfo?.name || bv[prop].id,
|
|
243
|
-
property: prop,
|
|
244
|
-
nodePath,
|
|
245
|
-
});
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
hardcodedValues.push({
|
|
249
|
-
property: prop,
|
|
250
|
-
value: node[prop],
|
|
251
|
-
nodePath,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
// Recurse into children
|
|
257
|
-
if (node.children && Array.isArray(node.children)) {
|
|
258
|
-
for (const child of node.children) {
|
|
259
|
-
walkForTokens(child, nodePath);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
};
|
|
263
|
-
walkForTokens(component);
|
|
264
|
-
enriched.variables_used = varsUsed;
|
|
265
|
-
enriched.hardcoded_values = hardcodedValues;
|
|
266
|
-
// Calculate token coverage
|
|
267
|
-
const totalProps = varsUsed.length + (enriched.styles_used?.length || 0) + hardcodedValues.length;
|
|
268
|
-
const tokenProps = varsUsed.length + (enriched.styles_used?.length || 0);
|
|
269
|
-
enriched.token_coverage =
|
|
270
|
-
totalProps > 0 ? Math.round((tokenProps / totalProps) * 100) : 100;
|
|
271
|
-
this.logger.info({ componentId: component.id, coverage: enriched.token_coverage }, "Component enrichment complete");
|
|
272
|
-
return enriched;
|
|
273
|
-
}
|
|
274
|
-
catch (error) {
|
|
275
|
-
this.logger.error({ error }, "Failed to enrich component");
|
|
276
|
-
return component;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
|
-
/**
|
|
280
|
-
* Enrich file data response
|
|
281
|
-
*/
|
|
282
|
-
async enrichFileData(fileData, options = {}) {
|
|
283
|
-
if (!options.enrich) {
|
|
284
|
-
return fileData;
|
|
285
|
-
}
|
|
286
|
-
this.logger.info({ fileKey: fileData.fileKey }, "Enriching file data");
|
|
287
|
-
try {
|
|
288
|
-
const enriched = {
|
|
289
|
-
...fileData,
|
|
290
|
-
};
|
|
291
|
-
// Build relationships for statistics
|
|
292
|
-
await this.relationshipMapper.buildRelationships(fileData);
|
|
293
|
-
// Calculate statistics
|
|
294
|
-
const styles = Object.values(fileData.styles || {});
|
|
295
|
-
const variables = Array.from(this.extractVariablesMap(fileData).values());
|
|
296
|
-
const unusedStyles = this.relationshipMapper.getUnusedStyles(styles);
|
|
297
|
-
const unusedVars = this.relationshipMapper.getUnusedVariables(variables);
|
|
298
|
-
enriched.statistics = {
|
|
299
|
-
total_variables: variables.length,
|
|
300
|
-
total_styles: styles.length,
|
|
301
|
-
total_components: Object.keys(fileData.components || {}).length,
|
|
302
|
-
unused_variables: unusedVars.length,
|
|
303
|
-
unused_styles: unusedStyles.length,
|
|
304
|
-
average_token_coverage: 0, // TODO: Calculate from components
|
|
305
|
-
total_hardcoded_values: 0, // TODO: Calculate from components
|
|
306
|
-
audit_issues_count: 0, // TODO: Calculate from audit
|
|
307
|
-
};
|
|
308
|
-
// Calculate health score (simple formula)
|
|
309
|
-
const usageRate = variables.length > 0
|
|
310
|
-
? ((variables.length - unusedVars.length) / variables.length) * 100
|
|
311
|
-
: 100;
|
|
312
|
-
enriched.health_score = Math.round(usageRate);
|
|
313
|
-
this.logger.info({ health_score: enriched.health_score }, "File data enrichment complete");
|
|
314
|
-
return enriched;
|
|
315
|
-
}
|
|
316
|
-
catch (error) {
|
|
317
|
-
this.logger.error({ error }, "Failed to enrich file data");
|
|
318
|
-
return fileData;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
/**
|
|
322
|
-
* Get file data for enrichment (with caching)
|
|
323
|
-
* NOTE: This is a placeholder that returns the data passed in
|
|
324
|
-
* In a full implementation, this would fetch fresh data from Figma API
|
|
325
|
-
*/
|
|
326
|
-
async getFileDataForEnrichment(fileKey, providedData) {
|
|
327
|
-
const now = Date.now();
|
|
328
|
-
const lastEnrich = this.lastEnrichmentTime.get(fileKey) || 0;
|
|
329
|
-
// Return cached if fresh
|
|
330
|
-
if (this.fileDataCache.has(fileKey) &&
|
|
331
|
-
now - lastEnrich < this.CACHE_TTL_MS) {
|
|
332
|
-
return this.fileDataCache.get(fileKey);
|
|
333
|
-
}
|
|
334
|
-
// If data is provided, use it (from the tool that called us)
|
|
335
|
-
// This avoids redundant API calls since the tool already fetched the data
|
|
336
|
-
const fileData = providedData || {
|
|
337
|
-
styles: {},
|
|
338
|
-
variables: {},
|
|
339
|
-
document: {},
|
|
340
|
-
components: {},
|
|
341
|
-
};
|
|
342
|
-
this.fileDataCache.set(fileKey, fileData);
|
|
343
|
-
this.lastEnrichmentTime.set(fileKey, now);
|
|
344
|
-
return fileData;
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Set file data in cache (called by tools that already have the data)
|
|
348
|
-
*/
|
|
349
|
-
setFileDataCache(fileKey, fileData) {
|
|
350
|
-
this.fileDataCache.set(fileKey, fileData);
|
|
351
|
-
this.lastEnrichmentTime.set(fileKey, Date.now());
|
|
352
|
-
}
|
|
353
|
-
/**
|
|
354
|
-
* Extract variables as a Map for efficient lookup
|
|
355
|
-
*/
|
|
356
|
-
extractVariablesMap(fileData) {
|
|
357
|
-
const variablesMap = new Map();
|
|
358
|
-
if (fileData.variables) {
|
|
359
|
-
for (const [id, variable] of Object.entries(fileData.variables)) {
|
|
360
|
-
variablesMap.set(id, variable);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
return variablesMap;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* Clear all caches
|
|
367
|
-
*/
|
|
368
|
-
clearCache() {
|
|
369
|
-
this.fileDataCache.clear();
|
|
370
|
-
this.lastEnrichmentTime.clear();
|
|
371
|
-
this.styleResolver.clearCache();
|
|
372
|
-
this.relationshipMapper.clear();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Enrichment module exports
|
|
3
|
-
* Phase 5: Enriched Data Extraction & Design System Auditing
|
|
4
|
-
*/
|
|
5
|
-
export { StyleValueResolver } from "./style-resolver.js";
|
|
6
|
-
export { RelationshipMapper } from "./relationship-mapper.js";
|
|
7
|
-
export { EnrichmentService } from "./enrichment-service.js";
|