@muloka/figma-console-mcp 0.5.0 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +3 -1
  2. package/dist/core/port-discovery.d.ts +9 -0
  3. package/dist/core/port-discovery.d.ts.map +1 -1
  4. package/dist/core/port-discovery.js +40 -14
  5. package/dist/core/port-discovery.js.map +1 -1
  6. package/dist/core/websocket-connector.d.ts +2 -1
  7. package/dist/core/websocket-connector.d.ts.map +1 -1
  8. package/dist/core/websocket-connector.js +17 -2
  9. package/dist/core/websocket-connector.js.map +1 -1
  10. package/dist/core/websocket-server.d.ts +8 -1
  11. package/dist/core/websocket-server.d.ts.map +1 -1
  12. package/dist/core/websocket-server.js +18 -2
  13. package/dist/core/websocket-server.js.map +1 -1
  14. package/dist/core/write-tools.d.ts +3 -1
  15. package/dist/core/write-tools.d.ts.map +1 -1
  16. package/dist/core/write-tools.js +34 -14
  17. package/dist/core/write-tools.js.map +1 -1
  18. package/dist/local.d.ts +2 -1
  19. package/dist/local.d.ts.map +1 -1
  20. package/dist/local.js +10 -14
  21. package/dist/local.js.map +1 -1
  22. package/package.json +1 -1
  23. package/dist/apps/design-system-dashboard/mcp-app.html +0 -521
  24. package/dist/apps/token-browser/mcp-app.html +0 -410
  25. package/dist/cloudflare/apps/design-system-dashboard/scoring/accessibility.js +0 -277
  26. package/dist/cloudflare/apps/design-system-dashboard/scoring/component-metadata.js +0 -357
  27. package/dist/cloudflare/apps/design-system-dashboard/scoring/consistency.js +0 -341
  28. package/dist/cloudflare/apps/design-system-dashboard/scoring/coverage.js +0 -230
  29. package/dist/cloudflare/apps/design-system-dashboard/scoring/engine.js +0 -92
  30. package/dist/cloudflare/apps/design-system-dashboard/scoring/naming-semantics.js +0 -308
  31. package/dist/cloudflare/apps/design-system-dashboard/scoring/token-architecture.js +0 -349
  32. package/dist/cloudflare/apps/design-system-dashboard/scoring/types.js +0 -40
  33. package/dist/cloudflare/apps/design-system-dashboard/server.js +0 -159
  34. package/dist/cloudflare/apps/token-browser/server.js +0 -136
  35. package/dist/cloudflare/browser-manager.js +0 -157
  36. package/dist/cloudflare/core/accessibility-tools.js +0 -361
  37. package/dist/cloudflare/core/annotation-tools.js +0 -230
  38. package/dist/cloudflare/core/cloud-websocket-connector.js +0 -419
  39. package/dist/cloudflare/core/cloud-websocket-relay.js +0 -198
  40. package/dist/cloudflare/core/comment-tools.js +0 -292
  41. package/dist/cloudflare/core/config.js +0 -153
  42. package/dist/cloudflare/core/console-monitor.js +0 -427
  43. package/dist/cloudflare/core/deep-component-tools.js +0 -128
  44. package/dist/cloudflare/core/design-code-tools.js +0 -2793
  45. package/dist/cloudflare/core/design-system-manifest.js +0 -265
  46. package/dist/cloudflare/core/design-system-tools.js +0 -882
  47. package/dist/cloudflare/core/diagnose-tool.js +0 -100
  48. package/dist/cloudflare/core/diff/changelog-formatter.js +0 -275
  49. package/dist/cloudflare/core/diff/diff-engine.js +0 -334
  50. package/dist/cloudflare/core/diff/property-compare.js +0 -36
  51. package/dist/cloudflare/core/diff/version-cache.js +0 -74
  52. package/dist/cloudflare/core/enrichment/enrichment-service.js +0 -374
  53. package/dist/cloudflare/core/enrichment/index.js +0 -7
  54. package/dist/cloudflare/core/enrichment/relationship-mapper.js +0 -351
  55. package/dist/cloudflare/core/enrichment/style-resolver.js +0 -346
  56. package/dist/cloudflare/core/figjam-tools.js +0 -547
  57. package/dist/cloudflare/core/figma-api.js +0 -509
  58. package/dist/cloudflare/core/figma-connector.js +0 -7
  59. package/dist/cloudflare/core/figma-reconstruction-spec.js +0 -402
  60. package/dist/cloudflare/core/figma-style-extractor.js +0 -311
  61. package/dist/cloudflare/core/figma-tools.js +0 -3353
  62. package/dist/cloudflare/core/identity.js +0 -96
  63. package/dist/cloudflare/core/library-tools.js +0 -580
  64. package/dist/cloudflare/core/logger.js +0 -53
  65. package/dist/cloudflare/core/port-discovery.js +0 -935
  66. package/dist/cloudflare/core/resolve-package-root.js +0 -11
  67. package/dist/cloudflare/core/slides-tools.js +0 -714
  68. package/dist/cloudflare/core/slot-tools.js +0 -334
  69. package/dist/cloudflare/core/snippet-injector.js +0 -96
  70. package/dist/cloudflare/core/tokens/alias-resolver.js +0 -205
  71. package/dist/cloudflare/core/tokens/config.js +0 -294
  72. package/dist/cloudflare/core/tokens/dialect.js +0 -232
  73. package/dist/cloudflare/core/tokens/figma-converter.js +0 -323
  74. package/dist/cloudflare/core/tokens/formatters/css-vars.js +0 -338
  75. package/dist/cloudflare/core/tokens/formatters/dtcg.js +0 -376
  76. package/dist/cloudflare/core/tokens/formatters/index.js +0 -45
  77. package/dist/cloudflare/core/tokens/formatters/json.js +0 -205
  78. package/dist/cloudflare/core/tokens/formatters/less.js +0 -4
  79. package/dist/cloudflare/core/tokens/formatters/scss.js +0 -258
  80. package/dist/cloudflare/core/tokens/formatters/stubs.js +0 -13
  81. package/dist/cloudflare/core/tokens/formatters/style-dictionary-v3.js +0 -213
  82. package/dist/cloudflare/core/tokens/formatters/tailwind-v3.js +0 -237
  83. package/dist/cloudflare/core/tokens/formatters/tailwind-v4.js +0 -335
  84. package/dist/cloudflare/core/tokens/formatters/tokens-studio.js +0 -256
  85. package/dist/cloudflare/core/tokens/formatters/ts-module.js +0 -198
  86. package/dist/cloudflare/core/tokens/index.js +0 -16
  87. package/dist/cloudflare/core/tokens/parsers/css-vars.js +0 -4
  88. package/dist/cloudflare/core/tokens/parsers/dtcg.js +0 -280
  89. package/dist/cloudflare/core/tokens/parsers/index.js +0 -138
  90. package/dist/cloudflare/core/tokens/parsers/json.js +0 -7
  91. package/dist/cloudflare/core/tokens/parsers/scss.js +0 -4
  92. package/dist/cloudflare/core/tokens/parsers/stubs.js +0 -20
  93. package/dist/cloudflare/core/tokens/parsers/style-dictionary-v3.js +0 -4
  94. package/dist/cloudflare/core/tokens/parsers/tailwind-v3.js +0 -4
  95. package/dist/cloudflare/core/tokens/parsers/tailwind-v4.js +0 -4
  96. package/dist/cloudflare/core/tokens/parsers/tokens-studio.js +0 -4
  97. package/dist/cloudflare/core/tokens/schemas.js +0 -152
  98. package/dist/cloudflare/core/tokens/transforms/color.js +0 -12
  99. package/dist/cloudflare/core/tokens/transforms/index.js +0 -29
  100. package/dist/cloudflare/core/tokens/transforms/size.js +0 -7
  101. package/dist/cloudflare/core/tokens/types.js +0 -18
  102. package/dist/cloudflare/core/tokens-tools.js +0 -1788
  103. package/dist/cloudflare/core/types/design-code.js +0 -4
  104. package/dist/cloudflare/core/types/enriched.js +0 -5
  105. package/dist/cloudflare/core/types/index.js +0 -4
  106. package/dist/cloudflare/core/variable-resolver.js +0 -85
  107. package/dist/cloudflare/core/version-tools.js +0 -1199
  108. package/dist/cloudflare/core/websocket-connector.js +0 -436
  109. package/dist/cloudflare/core/websocket-server.js +0 -1009
  110. package/dist/cloudflare/core/write-tools.js +0 -2506
  111. 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";