@mp3wizard/figma-console-mcp 1.14.0

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 (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +816 -0
  3. package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts +14 -0
  4. package/dist/apps/design-system-dashboard/scoring/accessibility.d.ts.map +1 -0
  5. package/dist/apps/design-system-dashboard/scoring/accessibility.js +278 -0
  6. package/dist/apps/design-system-dashboard/scoring/accessibility.js.map +1 -0
  7. package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts +29 -0
  8. package/dist/apps/design-system-dashboard/scoring/component-metadata.d.ts.map +1 -0
  9. package/dist/apps/design-system-dashboard/scoring/component-metadata.js +358 -0
  10. package/dist/apps/design-system-dashboard/scoring/component-metadata.js.map +1 -0
  11. package/dist/apps/design-system-dashboard/scoring/consistency.d.ts +14 -0
  12. package/dist/apps/design-system-dashboard/scoring/consistency.d.ts.map +1 -0
  13. package/dist/apps/design-system-dashboard/scoring/consistency.js +342 -0
  14. package/dist/apps/design-system-dashboard/scoring/consistency.js.map +1 -0
  15. package/dist/apps/design-system-dashboard/scoring/coverage.d.ts +14 -0
  16. package/dist/apps/design-system-dashboard/scoring/coverage.d.ts.map +1 -0
  17. package/dist/apps/design-system-dashboard/scoring/coverage.js +231 -0
  18. package/dist/apps/design-system-dashboard/scoring/coverage.js.map +1 -0
  19. package/dist/apps/design-system-dashboard/scoring/engine.d.ts +27 -0
  20. package/dist/apps/design-system-dashboard/scoring/engine.d.ts.map +1 -0
  21. package/dist/apps/design-system-dashboard/scoring/engine.js +93 -0
  22. package/dist/apps/design-system-dashboard/scoring/engine.js.map +1 -0
  23. package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts +14 -0
  24. package/dist/apps/design-system-dashboard/scoring/naming-semantics.d.ts.map +1 -0
  25. package/dist/apps/design-system-dashboard/scoring/naming-semantics.js +309 -0
  26. package/dist/apps/design-system-dashboard/scoring/naming-semantics.js.map +1 -0
  27. package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts +14 -0
  28. package/dist/apps/design-system-dashboard/scoring/token-architecture.d.ts.map +1 -0
  29. package/dist/apps/design-system-dashboard/scoring/token-architecture.js +350 -0
  30. package/dist/apps/design-system-dashboard/scoring/token-architecture.js.map +1 -0
  31. package/dist/apps/design-system-dashboard/scoring/types.d.ts +89 -0
  32. package/dist/apps/design-system-dashboard/scoring/types.d.ts.map +1 -0
  33. package/dist/apps/design-system-dashboard/scoring/types.js +41 -0
  34. package/dist/apps/design-system-dashboard/scoring/types.js.map +1 -0
  35. package/dist/apps/design-system-dashboard/server.d.ts +24 -0
  36. package/dist/apps/design-system-dashboard/server.d.ts.map +1 -0
  37. package/dist/apps/design-system-dashboard/server.js +160 -0
  38. package/dist/apps/design-system-dashboard/server.js.map +1 -0
  39. package/dist/apps/token-browser/server.d.ts +26 -0
  40. package/dist/apps/token-browser/server.d.ts.map +1 -0
  41. package/dist/apps/token-browser/server.js +137 -0
  42. package/dist/apps/token-browser/server.js.map +1 -0
  43. package/dist/browser/base.d.ts +58 -0
  44. package/dist/browser/base.d.ts.map +1 -0
  45. package/dist/browser/base.js +6 -0
  46. package/dist/browser/base.js.map +1 -0
  47. package/dist/browser/local.d.ts +87 -0
  48. package/dist/browser/local.d.ts.map +1 -0
  49. package/dist/browser/local.js +318 -0
  50. package/dist/browser/local.js.map +1 -0
  51. package/dist/cloudflare/apps/design-system-dashboard/scoring/accessibility.js +277 -0
  52. package/dist/cloudflare/apps/design-system-dashboard/scoring/component-metadata.js +357 -0
  53. package/dist/cloudflare/apps/design-system-dashboard/scoring/consistency.js +341 -0
  54. package/dist/cloudflare/apps/design-system-dashboard/scoring/coverage.js +230 -0
  55. package/dist/cloudflare/apps/design-system-dashboard/scoring/engine.js +92 -0
  56. package/dist/cloudflare/apps/design-system-dashboard/scoring/naming-semantics.js +308 -0
  57. package/dist/cloudflare/apps/design-system-dashboard/scoring/token-architecture.js +349 -0
  58. package/dist/cloudflare/apps/design-system-dashboard/scoring/types.js +40 -0
  59. package/dist/cloudflare/apps/design-system-dashboard/server.js +159 -0
  60. package/dist/cloudflare/apps/token-browser/server.js +136 -0
  61. package/dist/cloudflare/browser/base.js +5 -0
  62. package/dist/cloudflare/browser/cloudflare.js +156 -0
  63. package/dist/cloudflare/browser-manager.js +157 -0
  64. package/dist/cloudflare/core/cloud-websocket-connector.js +267 -0
  65. package/dist/cloudflare/core/cloud-websocket-relay.js +199 -0
  66. package/dist/cloudflare/core/comment-tools.js +292 -0
  67. package/dist/cloudflare/core/config.js +161 -0
  68. package/dist/cloudflare/core/console-monitor.js +427 -0
  69. package/dist/cloudflare/core/design-code-tools.js +2504 -0
  70. package/dist/cloudflare/core/design-system-manifest.js +260 -0
  71. package/dist/cloudflare/core/design-system-tools.js +863 -0
  72. package/dist/cloudflare/core/enrichment/enrichment-service.js +272 -0
  73. package/dist/cloudflare/core/enrichment/index.js +7 -0
  74. package/dist/cloudflare/core/enrichment/relationship-mapper.js +351 -0
  75. package/dist/cloudflare/core/enrichment/style-resolver.js +326 -0
  76. package/dist/cloudflare/core/figma-api.js +409 -0
  77. package/dist/cloudflare/core/figma-connector.js +7 -0
  78. package/dist/cloudflare/core/figma-desktop-connector.js +1184 -0
  79. package/dist/cloudflare/core/figma-reconstruction-spec.js +402 -0
  80. package/dist/cloudflare/core/figma-style-extractor.js +311 -0
  81. package/dist/cloudflare/core/figma-tools.js +2947 -0
  82. package/dist/cloudflare/core/logger.js +53 -0
  83. package/dist/cloudflare/core/port-discovery.js +282 -0
  84. package/dist/cloudflare/core/snippet-injector.js +96 -0
  85. package/dist/cloudflare/core/types/design-code.js +4 -0
  86. package/dist/cloudflare/core/types/enriched.js +5 -0
  87. package/dist/cloudflare/core/types/index.js +4 -0
  88. package/dist/cloudflare/core/websocket-connector.js +256 -0
  89. package/dist/cloudflare/core/websocket-server.js +646 -0
  90. package/dist/cloudflare/core/write-tools.js +2091 -0
  91. package/dist/cloudflare/index.js +2899 -0
  92. package/dist/cloudflare/test-browser.js +88 -0
  93. package/dist/core/comment-tools.d.ts +11 -0
  94. package/dist/core/comment-tools.d.ts.map +1 -0
  95. package/dist/core/comment-tools.js +293 -0
  96. package/dist/core/comment-tools.js.map +1 -0
  97. package/dist/core/config.d.ts +17 -0
  98. package/dist/core/config.d.ts.map +1 -0
  99. package/dist/core/config.js +162 -0
  100. package/dist/core/config.js.map +1 -0
  101. package/dist/core/console-monitor.d.ts +82 -0
  102. package/dist/core/console-monitor.d.ts.map +1 -0
  103. package/dist/core/console-monitor.js +428 -0
  104. package/dist/core/console-monitor.js.map +1 -0
  105. package/dist/core/design-code-tools.d.ts +127 -0
  106. package/dist/core/design-code-tools.d.ts.map +1 -0
  107. package/dist/core/design-code-tools.js +2505 -0
  108. package/dist/core/design-code-tools.js.map +1 -0
  109. package/dist/core/design-system-manifest.d.ts +272 -0
  110. package/dist/core/design-system-manifest.d.ts.map +1 -0
  111. package/dist/core/design-system-manifest.js +261 -0
  112. package/dist/core/design-system-manifest.js.map +1 -0
  113. package/dist/core/design-system-tools.d.ts +17 -0
  114. package/dist/core/design-system-tools.d.ts.map +1 -0
  115. package/dist/core/design-system-tools.js +864 -0
  116. package/dist/core/design-system-tools.js.map +1 -0
  117. package/dist/core/enrichment/enrichment-service.d.ts +52 -0
  118. package/dist/core/enrichment/enrichment-service.d.ts.map +1 -0
  119. package/dist/core/enrichment/enrichment-service.js +273 -0
  120. package/dist/core/enrichment/enrichment-service.js.map +1 -0
  121. package/dist/core/enrichment/index.d.ts +8 -0
  122. package/dist/core/enrichment/index.d.ts.map +1 -0
  123. package/dist/core/enrichment/index.js +8 -0
  124. package/dist/core/enrichment/index.js.map +1 -0
  125. package/dist/core/enrichment/relationship-mapper.d.ts +106 -0
  126. package/dist/core/enrichment/relationship-mapper.d.ts.map +1 -0
  127. package/dist/core/enrichment/relationship-mapper.js +352 -0
  128. package/dist/core/enrichment/relationship-mapper.js.map +1 -0
  129. package/dist/core/enrichment/style-resolver.d.ts +80 -0
  130. package/dist/core/enrichment/style-resolver.d.ts.map +1 -0
  131. package/dist/core/enrichment/style-resolver.js +327 -0
  132. package/dist/core/enrichment/style-resolver.js.map +1 -0
  133. package/dist/core/figma-api.d.ts +201 -0
  134. package/dist/core/figma-api.d.ts.map +1 -0
  135. package/dist/core/figma-api.js +410 -0
  136. package/dist/core/figma-api.js.map +1 -0
  137. package/dist/core/figma-connector.d.ts +48 -0
  138. package/dist/core/figma-connector.d.ts.map +1 -0
  139. package/dist/core/figma-connector.js +8 -0
  140. package/dist/core/figma-connector.js.map +1 -0
  141. package/dist/core/figma-desktop-connector.d.ts +265 -0
  142. package/dist/core/figma-desktop-connector.d.ts.map +1 -0
  143. package/dist/core/figma-desktop-connector.js +1184 -0
  144. package/dist/core/figma-desktop-connector.js.map +1 -0
  145. package/dist/core/figma-reconstruction-spec.d.ts +166 -0
  146. package/dist/core/figma-reconstruction-spec.d.ts.map +1 -0
  147. package/dist/core/figma-reconstruction-spec.js +403 -0
  148. package/dist/core/figma-reconstruction-spec.js.map +1 -0
  149. package/dist/core/figma-style-extractor.d.ts +76 -0
  150. package/dist/core/figma-style-extractor.d.ts.map +1 -0
  151. package/dist/core/figma-style-extractor.js +312 -0
  152. package/dist/core/figma-style-extractor.js.map +1 -0
  153. package/dist/core/figma-tools.d.ts +23 -0
  154. package/dist/core/figma-tools.d.ts.map +1 -0
  155. package/dist/core/figma-tools.js +2948 -0
  156. package/dist/core/figma-tools.js.map +1 -0
  157. package/dist/core/logger.d.ts +22 -0
  158. package/dist/core/logger.d.ts.map +1 -0
  159. package/dist/core/logger.js +54 -0
  160. package/dist/core/logger.js.map +1 -0
  161. package/dist/core/port-discovery.d.ts +110 -0
  162. package/dist/core/port-discovery.d.ts.map +1 -0
  163. package/dist/core/port-discovery.js +283 -0
  164. package/dist/core/port-discovery.js.map +1 -0
  165. package/dist/core/snippet-injector.d.ts +24 -0
  166. package/dist/core/snippet-injector.d.ts.map +1 -0
  167. package/dist/core/snippet-injector.js +97 -0
  168. package/dist/core/snippet-injector.js.map +1 -0
  169. package/dist/core/types/design-code.d.ts +262 -0
  170. package/dist/core/types/design-code.d.ts.map +1 -0
  171. package/dist/core/types/design-code.js +5 -0
  172. package/dist/core/types/design-code.js.map +1 -0
  173. package/dist/core/types/enriched.d.ts +213 -0
  174. package/dist/core/types/enriched.d.ts.map +1 -0
  175. package/dist/core/types/enriched.js +6 -0
  176. package/dist/core/types/enriched.js.map +1 -0
  177. package/dist/core/types/index.d.ts +112 -0
  178. package/dist/core/types/index.d.ts.map +1 -0
  179. package/dist/core/types/index.js +5 -0
  180. package/dist/core/types/index.js.map +1 -0
  181. package/dist/core/websocket-connector.d.ts +55 -0
  182. package/dist/core/websocket-connector.d.ts.map +1 -0
  183. package/dist/core/websocket-connector.js +257 -0
  184. package/dist/core/websocket-connector.js.map +1 -0
  185. package/dist/core/websocket-server.d.ts +191 -0
  186. package/dist/core/websocket-server.d.ts.map +1 -0
  187. package/dist/core/websocket-server.js +647 -0
  188. package/dist/core/websocket-server.js.map +1 -0
  189. package/dist/core/write-tools.d.ts +7 -0
  190. package/dist/core/write-tools.d.ts.map +1 -0
  191. package/dist/core/write-tools.js +2092 -0
  192. package/dist/core/write-tools.js.map +1 -0
  193. package/dist/local.d.ts +84 -0
  194. package/dist/local.d.ts.map +1 -0
  195. package/dist/local.js +5039 -0
  196. package/dist/local.js.map +1 -0
  197. package/figma-desktop-bridge/README.md +313 -0
  198. package/figma-desktop-bridge/code.js +2818 -0
  199. package/figma-desktop-bridge/manifest.json +67 -0
  200. package/figma-desktop-bridge/ui.html +1236 -0
  201. package/package.json +87 -0
@@ -0,0 +1,256 @@
1
+ /**
2
+ * WebSocket Figma Connector
3
+ *
4
+ * Implements IFigmaConnector using the WebSocket Desktop Bridge transport.
5
+ * Each method sends a command to the plugin UI via WebSocket and waits
6
+ * for the response — same window.* functions, different transport.
7
+ *
8
+ * Data flow: MCP Server ←WebSocket→ ui.html ←postMessage→ code.js ←figma.*→ Figma
9
+ */
10
+ import { createChildLogger } from './logger.js';
11
+ const logger = createChildLogger({ component: 'websocket-connector' });
12
+ export class WebSocketConnector {
13
+ constructor(wsServer) {
14
+ this.wsServer = wsServer;
15
+ }
16
+ async initialize() {
17
+ if (!this.wsServer.isClientConnected()) {
18
+ throw new Error('No WebSocket client connected. Make sure the Desktop Bridge plugin is open in Figma.');
19
+ }
20
+ logger.info('WebSocket connector initialized');
21
+ }
22
+ getTransportType() {
23
+ return 'websocket';
24
+ }
25
+ // ============================================================================
26
+ // Core execution
27
+ // ============================================================================
28
+ async executeInPluginContext(code) {
29
+ return this.wsServer.sendCommand('EXECUTE_CODE', { code, timeout: 5000 }, 7000);
30
+ }
31
+ async getVariablesFromPluginUI(fileKey) {
32
+ // Request the cached variables data that the plugin UI holds in window.__figmaVariablesData
33
+ return this.wsServer.sendCommand('GET_VARIABLES_DATA', {}, 10000, fileKey);
34
+ }
35
+ async getVariables(fileKey) {
36
+ // Execute the same variables-fetching code in the plugin worker context
37
+ const code = `
38
+ (async () => {
39
+ try {
40
+ if (typeof figma === 'undefined') {
41
+ throw new Error('Figma API not available in this context');
42
+ }
43
+ const variables = await figma.variables.getLocalVariablesAsync();
44
+ const collections = await figma.variables.getLocalVariableCollectionsAsync();
45
+ return {
46
+ success: true,
47
+ timestamp: Date.now(),
48
+ fileMetadata: { fileName: figma.root.name, fileKey: figma.fileKey || null },
49
+ variables: variables.map(function(v) { return { id: v.id, name: v.name, key: v.key, resolvedType: v.resolvedType, valuesByMode: v.valuesByMode, variableCollectionId: v.variableCollectionId, scopes: v.scopes, description: v.description, hiddenFromPublishing: v.hiddenFromPublishing }; }),
50
+ variableCollections: collections.map(function(c) { return { id: c.id, name: c.name, key: c.key, modes: c.modes, defaultModeId: c.defaultModeId, variableIds: c.variableIds }; })
51
+ };
52
+ } catch (error) {
53
+ return { success: false, error: error.message };
54
+ }
55
+ })()
56
+ `;
57
+ return this.wsServer.sendCommand('EXECUTE_CODE', { code, timeout: 30000 }, 32000, fileKey);
58
+ }
59
+ async executeCodeViaUI(code, timeoutMs = 5000) {
60
+ return this.wsServer.sendCommand('EXECUTE_CODE', { code, timeout: timeoutMs }, timeoutMs + 2000);
61
+ }
62
+ // ============================================================================
63
+ // Variable operations
64
+ // ============================================================================
65
+ async updateVariable(variableId, modeId, value) {
66
+ return this.wsServer.sendCommand('UPDATE_VARIABLE', { variableId, modeId, value });
67
+ }
68
+ async createVariable(name, collectionId, resolvedType, options) {
69
+ const params = { name, collectionId, resolvedType };
70
+ if (options) {
71
+ if (options.valuesByMode)
72
+ params.valuesByMode = options.valuesByMode;
73
+ if (options.description)
74
+ params.description = options.description;
75
+ if (options.scopes)
76
+ params.scopes = options.scopes;
77
+ }
78
+ return this.wsServer.sendCommand('CREATE_VARIABLE', params);
79
+ }
80
+ async deleteVariable(variableId) {
81
+ return this.wsServer.sendCommand('DELETE_VARIABLE', { variableId });
82
+ }
83
+ async refreshVariables() {
84
+ return this.wsServer.sendCommand('REFRESH_VARIABLES', {}, 300000);
85
+ }
86
+ async renameVariable(variableId, newName) {
87
+ const result = await this.wsServer.sendCommand('RENAME_VARIABLE', { variableId, newName });
88
+ // oldName may be embedded in variable data if ui.html handleResult doesn't pass it through
89
+ if (!result.oldName && result.variable?.oldName)
90
+ result.oldName = result.variable.oldName;
91
+ return result;
92
+ }
93
+ async setVariableDescription(variableId, description) {
94
+ return this.wsServer.sendCommand('SET_VARIABLE_DESCRIPTION', { variableId, description });
95
+ }
96
+ // ============================================================================
97
+ // Mode operations
98
+ // ============================================================================
99
+ async addMode(collectionId, modeName) {
100
+ return this.wsServer.sendCommand('ADD_MODE', { collectionId, modeName });
101
+ }
102
+ async renameMode(collectionId, modeId, newName) {
103
+ const result = await this.wsServer.sendCommand('RENAME_MODE', { collectionId, modeId, newName });
104
+ // oldName may be embedded in collection data if ui.html handleResult doesn't pass it through
105
+ if (!result.oldName && result.collection?.oldName)
106
+ result.oldName = result.collection.oldName;
107
+ return result;
108
+ }
109
+ // ============================================================================
110
+ // Collection operations
111
+ // ============================================================================
112
+ async createVariableCollection(name, options) {
113
+ const params = { name };
114
+ if (options) {
115
+ if (options.initialModeName)
116
+ params.initialModeName = options.initialModeName;
117
+ if (options.additionalModes)
118
+ params.additionalModes = options.additionalModes;
119
+ }
120
+ return this.wsServer.sendCommand('CREATE_VARIABLE_COLLECTION', params);
121
+ }
122
+ async deleteVariableCollection(collectionId) {
123
+ return this.wsServer.sendCommand('DELETE_VARIABLE_COLLECTION', { collectionId });
124
+ }
125
+ // ============================================================================
126
+ // Component operations
127
+ // ============================================================================
128
+ async getComponentFromPluginUI(nodeId) {
129
+ return this.wsServer.sendCommand('GET_COMPONENT', { nodeId }, 10000);
130
+ }
131
+ async getLocalComponents() {
132
+ return this.wsServer.sendCommand('GET_LOCAL_COMPONENTS', {}, 300000);
133
+ }
134
+ async setNodeDescription(nodeId, description, descriptionMarkdown) {
135
+ return this.wsServer.sendCommand('SET_NODE_DESCRIPTION', { nodeId, description, descriptionMarkdown });
136
+ }
137
+ async addComponentProperty(nodeId, propertyName, type, defaultValue, options) {
138
+ const params = { nodeId, propertyName, propertyType: type, defaultValue };
139
+ if (options?.preferredValues)
140
+ params.preferredValues = options.preferredValues;
141
+ return this.wsServer.sendCommand('ADD_COMPONENT_PROPERTY', params);
142
+ }
143
+ async editComponentProperty(nodeId, propertyName, newValue) {
144
+ return this.wsServer.sendCommand('EDIT_COMPONENT_PROPERTY', { nodeId, propertyName, newValue });
145
+ }
146
+ async deleteComponentProperty(nodeId, propertyName) {
147
+ return this.wsServer.sendCommand('DELETE_COMPONENT_PROPERTY', { nodeId, propertyName });
148
+ }
149
+ async instantiateComponent(componentKey, options) {
150
+ const params = { componentKey };
151
+ if (options) {
152
+ if (options.nodeId)
153
+ params.nodeId = options.nodeId;
154
+ if (options.position)
155
+ params.position = options.position;
156
+ if (options.size)
157
+ params.size = options.size;
158
+ if (options.overrides)
159
+ params.overrides = options.overrides;
160
+ if (options.variant)
161
+ params.variant = options.variant;
162
+ if (options.parentId)
163
+ params.parentId = options.parentId;
164
+ }
165
+ return this.wsServer.sendCommand('INSTANTIATE_COMPONENT', params);
166
+ }
167
+ // ============================================================================
168
+ // Node manipulation
169
+ // ============================================================================
170
+ async resizeNode(nodeId, width, height, withConstraints = true) {
171
+ return this.wsServer.sendCommand('RESIZE_NODE', { nodeId, width, height, withConstraints });
172
+ }
173
+ async moveNode(nodeId, x, y) {
174
+ return this.wsServer.sendCommand('MOVE_NODE', { nodeId, x, y });
175
+ }
176
+ async setNodeFills(nodeId, fills) {
177
+ return this.wsServer.sendCommand('SET_NODE_FILLS', { nodeId, fills });
178
+ }
179
+ async setNodeStrokes(nodeId, strokes, strokeWeight) {
180
+ const params = { nodeId, strokes };
181
+ if (strokeWeight !== undefined)
182
+ params.strokeWeight = strokeWeight;
183
+ return this.wsServer.sendCommand('SET_NODE_STROKES', params);
184
+ }
185
+ async setNodeOpacity(nodeId, opacity) {
186
+ return this.wsServer.sendCommand('SET_NODE_OPACITY', { nodeId, opacity });
187
+ }
188
+ async setNodeCornerRadius(nodeId, radius) {
189
+ return this.wsServer.sendCommand('SET_NODE_CORNER_RADIUS', { nodeId, radius });
190
+ }
191
+ async cloneNode(nodeId) {
192
+ return this.wsServer.sendCommand('CLONE_NODE', { nodeId });
193
+ }
194
+ async deleteNode(nodeId) {
195
+ return this.wsServer.sendCommand('DELETE_NODE', { nodeId });
196
+ }
197
+ async renameNode(nodeId, newName) {
198
+ return this.wsServer.sendCommand('RENAME_NODE', { nodeId, newName });
199
+ }
200
+ async setTextContent(nodeId, characters, options) {
201
+ const params = { nodeId, text: characters };
202
+ if (options) {
203
+ if (options.fontSize)
204
+ params.fontSize = options.fontSize;
205
+ if (options.fontWeight)
206
+ params.fontWeight = options.fontWeight;
207
+ if (options.fontFamily)
208
+ params.fontFamily = options.fontFamily;
209
+ }
210
+ return this.wsServer.sendCommand('SET_TEXT_CONTENT', params);
211
+ }
212
+ async createChildNode(parentId, nodeType, properties) {
213
+ return this.wsServer.sendCommand('CREATE_CHILD_NODE', { parentId, nodeType, properties: properties || {} });
214
+ }
215
+ // ============================================================================
216
+ // Screenshot & instance properties
217
+ // ============================================================================
218
+ async captureScreenshot(nodeId, options) {
219
+ const params = { nodeId };
220
+ if (options?.format)
221
+ params.format = options.format;
222
+ if (options?.scale)
223
+ params.scale = options.scale;
224
+ return this.wsServer.sendCommand('CAPTURE_SCREENSHOT', params, 30000);
225
+ }
226
+ async setInstanceProperties(nodeId, properties) {
227
+ return this.wsServer.sendCommand('SET_INSTANCE_PROPERTIES', { nodeId, properties });
228
+ }
229
+ // ============================================================================
230
+ // Image fill
231
+ // ============================================================================
232
+ async setImageFill(nodeIds, imageData, scaleMode = 'FILL') {
233
+ return this.wsServer.sendCommand('SET_IMAGE_FILL', { nodeIds, imageData, scaleMode }, 60000);
234
+ }
235
+ // ============================================================================
236
+ // Design lint
237
+ // ============================================================================
238
+ async lintDesign(nodeId, rules, maxDepth, maxFindings) {
239
+ const params = {};
240
+ if (nodeId)
241
+ params.nodeId = nodeId;
242
+ if (rules)
243
+ params.rules = rules;
244
+ if (maxDepth !== undefined)
245
+ params.maxDepth = maxDepth;
246
+ if (maxFindings !== undefined)
247
+ params.maxFindings = maxFindings;
248
+ return this.wsServer.sendCommand('LINT_DESIGN', params, 120000);
249
+ }
250
+ // ============================================================================
251
+ // Cache management (no-op for WebSocket — no frame cache)
252
+ // ============================================================================
253
+ clearFrameCache() {
254
+ // No frame cache in WebSocket mode
255
+ }
256
+ }