@muloka/figma-console-mcp 0.1.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 (443) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +898 -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-manager.js +157 -0
  62. package/dist/cloudflare/core/accessibility-tools.js +361 -0
  63. package/dist/cloudflare/core/annotation-tools.js +230 -0
  64. package/dist/cloudflare/core/cloud-websocket-connector.js +419 -0
  65. package/dist/cloudflare/core/cloud-websocket-relay.js +198 -0
  66. package/dist/cloudflare/core/comment-tools.js +292 -0
  67. package/dist/cloudflare/core/config.js +153 -0
  68. package/dist/cloudflare/core/console-monitor.js +427 -0
  69. package/dist/cloudflare/core/deep-component-tools.js +128 -0
  70. package/dist/cloudflare/core/design-code-tools.js +2793 -0
  71. package/dist/cloudflare/core/design-system-manifest.js +265 -0
  72. package/dist/cloudflare/core/design-system-tools.js +882 -0
  73. package/dist/cloudflare/core/diagnose-tool.js +100 -0
  74. package/dist/cloudflare/core/diff/changelog-formatter.js +275 -0
  75. package/dist/cloudflare/core/diff/diff-engine.js +334 -0
  76. package/dist/cloudflare/core/diff/property-compare.js +36 -0
  77. package/dist/cloudflare/core/diff/version-cache.js +74 -0
  78. package/dist/cloudflare/core/enrichment/enrichment-service.js +374 -0
  79. package/dist/cloudflare/core/enrichment/index.js +7 -0
  80. package/dist/cloudflare/core/enrichment/relationship-mapper.js +351 -0
  81. package/dist/cloudflare/core/enrichment/style-resolver.js +346 -0
  82. package/dist/cloudflare/core/figjam-tools.js +547 -0
  83. package/dist/cloudflare/core/figma-api.js +509 -0
  84. package/dist/cloudflare/core/figma-connector.js +7 -0
  85. package/dist/cloudflare/core/figma-reconstruction-spec.js +402 -0
  86. package/dist/cloudflare/core/figma-style-extractor.js +311 -0
  87. package/dist/cloudflare/core/figma-tools.js +3302 -0
  88. package/dist/cloudflare/core/identity.js +96 -0
  89. package/dist/cloudflare/core/library-tools.js +580 -0
  90. package/dist/cloudflare/core/logger.js +53 -0
  91. package/dist/cloudflare/core/port-discovery.js +935 -0
  92. package/dist/cloudflare/core/resolve-package-root.js +11 -0
  93. package/dist/cloudflare/core/slides-tools.js +714 -0
  94. package/dist/cloudflare/core/slot-tools.js +334 -0
  95. package/dist/cloudflare/core/snippet-injector.js +96 -0
  96. package/dist/cloudflare/core/tokens/alias-resolver.js +205 -0
  97. package/dist/cloudflare/core/tokens/config.js +294 -0
  98. package/dist/cloudflare/core/tokens/dialect.js +232 -0
  99. package/dist/cloudflare/core/tokens/figma-converter.js +323 -0
  100. package/dist/cloudflare/core/tokens/formatters/css-vars.js +338 -0
  101. package/dist/cloudflare/core/tokens/formatters/dtcg.js +376 -0
  102. package/dist/cloudflare/core/tokens/formatters/index.js +45 -0
  103. package/dist/cloudflare/core/tokens/formatters/json.js +205 -0
  104. package/dist/cloudflare/core/tokens/formatters/less.js +4 -0
  105. package/dist/cloudflare/core/tokens/formatters/scss.js +258 -0
  106. package/dist/cloudflare/core/tokens/formatters/stubs.js +13 -0
  107. package/dist/cloudflare/core/tokens/formatters/style-dictionary-v3.js +213 -0
  108. package/dist/cloudflare/core/tokens/formatters/tailwind-v3.js +237 -0
  109. package/dist/cloudflare/core/tokens/formatters/tailwind-v4.js +335 -0
  110. package/dist/cloudflare/core/tokens/formatters/tokens-studio.js +256 -0
  111. package/dist/cloudflare/core/tokens/formatters/ts-module.js +198 -0
  112. package/dist/cloudflare/core/tokens/index.js +16 -0
  113. package/dist/cloudflare/core/tokens/parsers/css-vars.js +4 -0
  114. package/dist/cloudflare/core/tokens/parsers/dtcg.js +280 -0
  115. package/dist/cloudflare/core/tokens/parsers/index.js +138 -0
  116. package/dist/cloudflare/core/tokens/parsers/json.js +7 -0
  117. package/dist/cloudflare/core/tokens/parsers/scss.js +4 -0
  118. package/dist/cloudflare/core/tokens/parsers/stubs.js +20 -0
  119. package/dist/cloudflare/core/tokens/parsers/style-dictionary-v3.js +4 -0
  120. package/dist/cloudflare/core/tokens/parsers/tailwind-v3.js +4 -0
  121. package/dist/cloudflare/core/tokens/parsers/tailwind-v4.js +4 -0
  122. package/dist/cloudflare/core/tokens/parsers/tokens-studio.js +4 -0
  123. package/dist/cloudflare/core/tokens/schemas.js +152 -0
  124. package/dist/cloudflare/core/tokens/transforms/color.js +12 -0
  125. package/dist/cloudflare/core/tokens/transforms/index.js +29 -0
  126. package/dist/cloudflare/core/tokens/transforms/size.js +7 -0
  127. package/dist/cloudflare/core/tokens/types.js +18 -0
  128. package/dist/cloudflare/core/tokens-tools.js +1788 -0
  129. package/dist/cloudflare/core/types/design-code.js +4 -0
  130. package/dist/cloudflare/core/types/enriched.js +5 -0
  131. package/dist/cloudflare/core/types/index.js +4 -0
  132. package/dist/cloudflare/core/variable-resolver.js +85 -0
  133. package/dist/cloudflare/core/version-tools.js +1199 -0
  134. package/dist/cloudflare/core/websocket-connector.js +436 -0
  135. package/dist/cloudflare/core/websocket-server.js +956 -0
  136. package/dist/cloudflare/core/write-tools.js +2506 -0
  137. package/dist/cloudflare/index.js +3010 -0
  138. package/dist/core/accessibility-tools.d.ts +21 -0
  139. package/dist/core/accessibility-tools.d.ts.map +1 -0
  140. package/dist/core/accessibility-tools.js +362 -0
  141. package/dist/core/accessibility-tools.js.map +1 -0
  142. package/dist/core/annotation-tools.d.ts +14 -0
  143. package/dist/core/annotation-tools.d.ts.map +1 -0
  144. package/dist/core/annotation-tools.js +231 -0
  145. package/dist/core/annotation-tools.js.map +1 -0
  146. package/dist/core/comment-tools.d.ts +11 -0
  147. package/dist/core/comment-tools.d.ts.map +1 -0
  148. package/dist/core/comment-tools.js +293 -0
  149. package/dist/core/comment-tools.js.map +1 -0
  150. package/dist/core/config.d.ts +17 -0
  151. package/dist/core/config.d.ts.map +1 -0
  152. package/dist/core/config.js +154 -0
  153. package/dist/core/config.js.map +1 -0
  154. package/dist/core/console-monitor.d.ts +82 -0
  155. package/dist/core/console-monitor.d.ts.map +1 -0
  156. package/dist/core/console-monitor.js +428 -0
  157. package/dist/core/console-monitor.js.map +1 -0
  158. package/dist/core/deep-component-tools.d.ts +14 -0
  159. package/dist/core/deep-component-tools.d.ts.map +1 -0
  160. package/dist/core/deep-component-tools.js +129 -0
  161. package/dist/core/deep-component-tools.js.map +1 -0
  162. package/dist/core/design-code-tools.d.ts +116 -0
  163. package/dist/core/design-code-tools.d.ts.map +1 -0
  164. package/dist/core/design-code-tools.js +2794 -0
  165. package/dist/core/design-code-tools.js.map +1 -0
  166. package/dist/core/design-system-manifest.d.ts +273 -0
  167. package/dist/core/design-system-manifest.d.ts.map +1 -0
  168. package/dist/core/design-system-manifest.js +266 -0
  169. package/dist/core/design-system-manifest.js.map +1 -0
  170. package/dist/core/design-system-tools.d.ts +67 -0
  171. package/dist/core/design-system-tools.d.ts.map +1 -0
  172. package/dist/core/design-system-tools.js +883 -0
  173. package/dist/core/design-system-tools.js.map +1 -0
  174. package/dist/core/diagnose-tool.d.ts +41 -0
  175. package/dist/core/diagnose-tool.d.ts.map +1 -0
  176. package/dist/core/diagnose-tool.js +101 -0
  177. package/dist/core/diagnose-tool.js.map +1 -0
  178. package/dist/core/diff/changelog-formatter.d.ts +35 -0
  179. package/dist/core/diff/changelog-formatter.d.ts.map +1 -0
  180. package/dist/core/diff/changelog-formatter.js +276 -0
  181. package/dist/core/diff/changelog-formatter.js.map +1 -0
  182. package/dist/core/diff/diff-engine.d.ts +127 -0
  183. package/dist/core/diff/diff-engine.d.ts.map +1 -0
  184. package/dist/core/diff/diff-engine.js +335 -0
  185. package/dist/core/diff/diff-engine.js.map +1 -0
  186. package/dist/core/diff/property-compare.d.ts +19 -0
  187. package/dist/core/diff/property-compare.d.ts.map +1 -0
  188. package/dist/core/diff/property-compare.js +37 -0
  189. package/dist/core/diff/property-compare.js.map +1 -0
  190. package/dist/core/diff/version-cache.d.ts +40 -0
  191. package/dist/core/diff/version-cache.d.ts.map +1 -0
  192. package/dist/core/diff/version-cache.js +75 -0
  193. package/dist/core/diff/version-cache.js.map +1 -0
  194. package/dist/core/enrichment/enrichment-service.d.ts +52 -0
  195. package/dist/core/enrichment/enrichment-service.d.ts.map +1 -0
  196. package/dist/core/enrichment/enrichment-service.js +375 -0
  197. package/dist/core/enrichment/enrichment-service.js.map +1 -0
  198. package/dist/core/enrichment/index.d.ts +8 -0
  199. package/dist/core/enrichment/index.d.ts.map +1 -0
  200. package/dist/core/enrichment/index.js +8 -0
  201. package/dist/core/enrichment/index.js.map +1 -0
  202. package/dist/core/enrichment/relationship-mapper.d.ts +106 -0
  203. package/dist/core/enrichment/relationship-mapper.d.ts.map +1 -0
  204. package/dist/core/enrichment/relationship-mapper.js +352 -0
  205. package/dist/core/enrichment/relationship-mapper.js.map +1 -0
  206. package/dist/core/enrichment/style-resolver.d.ts +85 -0
  207. package/dist/core/enrichment/style-resolver.d.ts.map +1 -0
  208. package/dist/core/enrichment/style-resolver.js +347 -0
  209. package/dist/core/enrichment/style-resolver.js.map +1 -0
  210. package/dist/core/figjam-tools.d.ts +8 -0
  211. package/dist/core/figjam-tools.d.ts.map +1 -0
  212. package/dist/core/figjam-tools.js +548 -0
  213. package/dist/core/figjam-tools.js.map +1 -0
  214. package/dist/core/figma-api.d.ts +254 -0
  215. package/dist/core/figma-api.d.ts.map +1 -0
  216. package/dist/core/figma-api.js +510 -0
  217. package/dist/core/figma-api.js.map +1 -0
  218. package/dist/core/figma-connector.d.ts +214 -0
  219. package/dist/core/figma-connector.d.ts.map +1 -0
  220. package/dist/core/figma-connector.js +8 -0
  221. package/dist/core/figma-connector.js.map +1 -0
  222. package/dist/core/figma-desktop-connector.d.ts +312 -0
  223. package/dist/core/figma-desktop-connector.d.ts.map +1 -0
  224. package/dist/core/figma-desktop-connector.js +1298 -0
  225. package/dist/core/figma-desktop-connector.js.map +1 -0
  226. package/dist/core/figma-reconstruction-spec.d.ts +166 -0
  227. package/dist/core/figma-reconstruction-spec.d.ts.map +1 -0
  228. package/dist/core/figma-reconstruction-spec.js +403 -0
  229. package/dist/core/figma-reconstruction-spec.js.map +1 -0
  230. package/dist/core/figma-style-extractor.d.ts +76 -0
  231. package/dist/core/figma-style-extractor.d.ts.map +1 -0
  232. package/dist/core/figma-style-extractor.js +312 -0
  233. package/dist/core/figma-style-extractor.js.map +1 -0
  234. package/dist/core/figma-tools.d.ts +22 -0
  235. package/dist/core/figma-tools.d.ts.map +1 -0
  236. package/dist/core/figma-tools.js +3303 -0
  237. package/dist/core/figma-tools.js.map +1 -0
  238. package/dist/core/identity.d.ts +41 -0
  239. package/dist/core/identity.d.ts.map +1 -0
  240. package/dist/core/identity.js +97 -0
  241. package/dist/core/identity.js.map +1 -0
  242. package/dist/core/library-tools.d.ts +17 -0
  243. package/dist/core/library-tools.d.ts.map +1 -0
  244. package/dist/core/library-tools.js +581 -0
  245. package/dist/core/library-tools.js.map +1 -0
  246. package/dist/core/logger.d.ts +22 -0
  247. package/dist/core/logger.d.ts.map +1 -0
  248. package/dist/core/logger.js +54 -0
  249. package/dist/core/logger.js.map +1 -0
  250. package/dist/core/port-discovery.d.ts +211 -0
  251. package/dist/core/port-discovery.d.ts.map +1 -0
  252. package/dist/core/port-discovery.js +936 -0
  253. package/dist/core/port-discovery.js.map +1 -0
  254. package/dist/core/resolve-package-root.d.ts +2 -0
  255. package/dist/core/resolve-package-root.d.ts.map +1 -0
  256. package/dist/core/resolve-package-root.js +12 -0
  257. package/dist/core/resolve-package-root.js.map +1 -0
  258. package/dist/core/slides-tools.d.ts +8 -0
  259. package/dist/core/slides-tools.d.ts.map +1 -0
  260. package/dist/core/slides-tools.js +715 -0
  261. package/dist/core/slides-tools.js.map +1 -0
  262. package/dist/core/slot-tools.d.ts +7 -0
  263. package/dist/core/slot-tools.d.ts.map +1 -0
  264. package/dist/core/slot-tools.js +335 -0
  265. package/dist/core/slot-tools.js.map +1 -0
  266. package/dist/core/snippet-injector.d.ts +24 -0
  267. package/dist/core/snippet-injector.d.ts.map +1 -0
  268. package/dist/core/snippet-injector.js +97 -0
  269. package/dist/core/snippet-injector.js.map +1 -0
  270. package/dist/core/tokens/alias-resolver.d.ts +97 -0
  271. package/dist/core/tokens/alias-resolver.d.ts.map +1 -0
  272. package/dist/core/tokens/alias-resolver.js +206 -0
  273. package/dist/core/tokens/alias-resolver.js.map +1 -0
  274. package/dist/core/tokens/config.d.ts +380 -0
  275. package/dist/core/tokens/config.d.ts.map +1 -0
  276. package/dist/core/tokens/config.js +295 -0
  277. package/dist/core/tokens/config.js.map +1 -0
  278. package/dist/core/tokens/dialect.d.ts +107 -0
  279. package/dist/core/tokens/dialect.d.ts.map +1 -0
  280. package/dist/core/tokens/dialect.js +233 -0
  281. package/dist/core/tokens/dialect.js.map +1 -0
  282. package/dist/core/tokens/figma-converter.d.ts +102 -0
  283. package/dist/core/tokens/figma-converter.d.ts.map +1 -0
  284. package/dist/core/tokens/figma-converter.js +324 -0
  285. package/dist/core/tokens/figma-converter.js.map +1 -0
  286. package/dist/core/tokens/formatters/css-vars.d.ts +24 -0
  287. package/dist/core/tokens/formatters/css-vars.d.ts.map +1 -0
  288. package/dist/core/tokens/formatters/css-vars.js +339 -0
  289. package/dist/core/tokens/formatters/css-vars.js.map +1 -0
  290. package/dist/core/tokens/formatters/dtcg.d.ts +28 -0
  291. package/dist/core/tokens/formatters/dtcg.d.ts.map +1 -0
  292. package/dist/core/tokens/formatters/dtcg.js +377 -0
  293. package/dist/core/tokens/formatters/dtcg.js.map +1 -0
  294. package/dist/core/tokens/formatters/index.d.ts +30 -0
  295. package/dist/core/tokens/formatters/index.d.ts.map +1 -0
  296. package/dist/core/tokens/formatters/index.js +46 -0
  297. package/dist/core/tokens/formatters/index.js.map +1 -0
  298. package/dist/core/tokens/formatters/json.d.ts +37 -0
  299. package/dist/core/tokens/formatters/json.d.ts.map +1 -0
  300. package/dist/core/tokens/formatters/json.js +206 -0
  301. package/dist/core/tokens/formatters/json.js.map +1 -0
  302. package/dist/core/tokens/formatters/less.d.ts +4 -0
  303. package/dist/core/tokens/formatters/less.d.ts.map +1 -0
  304. package/dist/core/tokens/formatters/less.js +5 -0
  305. package/dist/core/tokens/formatters/less.js.map +1 -0
  306. package/dist/core/tokens/formatters/scss.d.ts +26 -0
  307. package/dist/core/tokens/formatters/scss.d.ts.map +1 -0
  308. package/dist/core/tokens/formatters/scss.js +259 -0
  309. package/dist/core/tokens/formatters/scss.js.map +1 -0
  310. package/dist/core/tokens/formatters/stubs.d.ts +9 -0
  311. package/dist/core/tokens/formatters/stubs.d.ts.map +1 -0
  312. package/dist/core/tokens/formatters/stubs.js +14 -0
  313. package/dist/core/tokens/formatters/stubs.js.map +1 -0
  314. package/dist/core/tokens/formatters/style-dictionary-v3.d.ts +45 -0
  315. package/dist/core/tokens/formatters/style-dictionary-v3.d.ts.map +1 -0
  316. package/dist/core/tokens/formatters/style-dictionary-v3.js +214 -0
  317. package/dist/core/tokens/formatters/style-dictionary-v3.js.map +1 -0
  318. package/dist/core/tokens/formatters/tailwind-v3.d.ts +37 -0
  319. package/dist/core/tokens/formatters/tailwind-v3.d.ts.map +1 -0
  320. package/dist/core/tokens/formatters/tailwind-v3.js +238 -0
  321. package/dist/core/tokens/formatters/tailwind-v3.js.map +1 -0
  322. package/dist/core/tokens/formatters/tailwind-v4.d.ts +41 -0
  323. package/dist/core/tokens/formatters/tailwind-v4.d.ts.map +1 -0
  324. package/dist/core/tokens/formatters/tailwind-v4.js +336 -0
  325. package/dist/core/tokens/formatters/tailwind-v4.js.map +1 -0
  326. package/dist/core/tokens/formatters/tokens-studio.d.ts +44 -0
  327. package/dist/core/tokens/formatters/tokens-studio.d.ts.map +1 -0
  328. package/dist/core/tokens/formatters/tokens-studio.js +257 -0
  329. package/dist/core/tokens/formatters/tokens-studio.js.map +1 -0
  330. package/dist/core/tokens/formatters/ts-module.d.ts +35 -0
  331. package/dist/core/tokens/formatters/ts-module.d.ts.map +1 -0
  332. package/dist/core/tokens/formatters/ts-module.js +199 -0
  333. package/dist/core/tokens/formatters/ts-module.js.map +1 -0
  334. package/dist/core/tokens/index.d.ts +18 -0
  335. package/dist/core/tokens/index.d.ts.map +1 -0
  336. package/dist/core/tokens/index.js +17 -0
  337. package/dist/core/tokens/index.js.map +1 -0
  338. package/dist/core/tokens/parsers/css-vars.d.ts +3 -0
  339. package/dist/core/tokens/parsers/css-vars.d.ts.map +1 -0
  340. package/dist/core/tokens/parsers/css-vars.js +5 -0
  341. package/dist/core/tokens/parsers/css-vars.js.map +1 -0
  342. package/dist/core/tokens/parsers/dtcg.d.ts +21 -0
  343. package/dist/core/tokens/parsers/dtcg.d.ts.map +1 -0
  344. package/dist/core/tokens/parsers/dtcg.js +281 -0
  345. package/dist/core/tokens/parsers/dtcg.js.map +1 -0
  346. package/dist/core/tokens/parsers/index.d.ts +37 -0
  347. package/dist/core/tokens/parsers/index.d.ts.map +1 -0
  348. package/dist/core/tokens/parsers/index.js +139 -0
  349. package/dist/core/tokens/parsers/index.js.map +1 -0
  350. package/dist/core/tokens/parsers/json.d.ts +4 -0
  351. package/dist/core/tokens/parsers/json.d.ts.map +1 -0
  352. package/dist/core/tokens/parsers/json.js +8 -0
  353. package/dist/core/tokens/parsers/json.js.map +1 -0
  354. package/dist/core/tokens/parsers/scss.d.ts +3 -0
  355. package/dist/core/tokens/parsers/scss.d.ts.map +1 -0
  356. package/dist/core/tokens/parsers/scss.js +5 -0
  357. package/dist/core/tokens/parsers/scss.js.map +1 -0
  358. package/dist/core/tokens/parsers/stubs.d.ts +15 -0
  359. package/dist/core/tokens/parsers/stubs.d.ts.map +1 -0
  360. package/dist/core/tokens/parsers/stubs.js +21 -0
  361. package/dist/core/tokens/parsers/stubs.js.map +1 -0
  362. package/dist/core/tokens/parsers/style-dictionary-v3.d.ts +3 -0
  363. package/dist/core/tokens/parsers/style-dictionary-v3.d.ts.map +1 -0
  364. package/dist/core/tokens/parsers/style-dictionary-v3.js +5 -0
  365. package/dist/core/tokens/parsers/style-dictionary-v3.js.map +1 -0
  366. package/dist/core/tokens/parsers/tailwind-v3.d.ts +3 -0
  367. package/dist/core/tokens/parsers/tailwind-v3.d.ts.map +1 -0
  368. package/dist/core/tokens/parsers/tailwind-v3.js +5 -0
  369. package/dist/core/tokens/parsers/tailwind-v3.js.map +1 -0
  370. package/dist/core/tokens/parsers/tailwind-v4.d.ts +3 -0
  371. package/dist/core/tokens/parsers/tailwind-v4.d.ts.map +1 -0
  372. package/dist/core/tokens/parsers/tailwind-v4.js +5 -0
  373. package/dist/core/tokens/parsers/tailwind-v4.js.map +1 -0
  374. package/dist/core/tokens/parsers/tokens-studio.d.ts +3 -0
  375. package/dist/core/tokens/parsers/tokens-studio.d.ts.map +1 -0
  376. package/dist/core/tokens/parsers/tokens-studio.js +5 -0
  377. package/dist/core/tokens/parsers/tokens-studio.js.map +1 -0
  378. package/dist/core/tokens/schemas.d.ts +155 -0
  379. package/dist/core/tokens/schemas.d.ts.map +1 -0
  380. package/dist/core/tokens/schemas.js +153 -0
  381. package/dist/core/tokens/schemas.js.map +1 -0
  382. package/dist/core/tokens/transforms/color.d.ts +9 -0
  383. package/dist/core/tokens/transforms/color.d.ts.map +1 -0
  384. package/dist/core/tokens/transforms/color.js +13 -0
  385. package/dist/core/tokens/transforms/color.js.map +1 -0
  386. package/dist/core/tokens/transforms/index.d.ts +36 -0
  387. package/dist/core/tokens/transforms/index.d.ts.map +1 -0
  388. package/dist/core/tokens/transforms/index.js +30 -0
  389. package/dist/core/tokens/transforms/index.js.map +1 -0
  390. package/dist/core/tokens/transforms/size.d.ts +7 -0
  391. package/dist/core/tokens/transforms/size.d.ts.map +1 -0
  392. package/dist/core/tokens/transforms/size.js +8 -0
  393. package/dist/core/tokens/transforms/size.js.map +1 -0
  394. package/dist/core/tokens/types.d.ts +284 -0
  395. package/dist/core/tokens/types.d.ts.map +1 -0
  396. package/dist/core/tokens/types.js +19 -0
  397. package/dist/core/tokens/types.js.map +1 -0
  398. package/dist/core/tokens-tools.d.ts +285 -0
  399. package/dist/core/tokens-tools.d.ts.map +1 -0
  400. package/dist/core/tokens-tools.js +1789 -0
  401. package/dist/core/tokens-tools.js.map +1 -0
  402. package/dist/core/types/design-code.d.ts +271 -0
  403. package/dist/core/types/design-code.d.ts.map +1 -0
  404. package/dist/core/types/design-code.js +5 -0
  405. package/dist/core/types/design-code.js.map +1 -0
  406. package/dist/core/types/enriched.d.ts +213 -0
  407. package/dist/core/types/enriched.d.ts.map +1 -0
  408. package/dist/core/types/enriched.js +6 -0
  409. package/dist/core/types/enriched.js.map +1 -0
  410. package/dist/core/types/index.d.ts +104 -0
  411. package/dist/core/types/index.d.ts.map +1 -0
  412. package/dist/core/types/index.js +5 -0
  413. package/dist/core/types/index.js.map +1 -0
  414. package/dist/core/variable-resolver.d.ts +45 -0
  415. package/dist/core/variable-resolver.d.ts.map +1 -0
  416. package/dist/core/variable-resolver.js +86 -0
  417. package/dist/core/variable-resolver.js.map +1 -0
  418. package/dist/core/version-tools.d.ts +59 -0
  419. package/dist/core/version-tools.d.ts.map +1 -0
  420. package/dist/core/version-tools.js +1200 -0
  421. package/dist/core/version-tools.js.map +1 -0
  422. package/dist/core/websocket-connector.d.ts +247 -0
  423. package/dist/core/websocket-connector.d.ts.map +1 -0
  424. package/dist/core/websocket-connector.js +437 -0
  425. package/dist/core/websocket-connector.js.map +1 -0
  426. package/dist/core/websocket-server.d.ts +290 -0
  427. package/dist/core/websocket-server.d.ts.map +1 -0
  428. package/dist/core/websocket-server.js +957 -0
  429. package/dist/core/websocket-server.js.map +1 -0
  430. package/dist/core/write-tools.d.ts +7 -0
  431. package/dist/core/write-tools.d.ts.map +1 -0
  432. package/dist/core/write-tools.js +2507 -0
  433. package/dist/core/write-tools.js.map +1 -0
  434. package/dist/local.d.ts +105 -0
  435. package/dist/local.d.ts.map +1 -0
  436. package/dist/local.js +3314 -0
  437. package/dist/local.js.map +1 -0
  438. package/figma-desktop-bridge/README.md +365 -0
  439. package/figma-desktop-bridge/code.js +7359 -0
  440. package/figma-desktop-bridge/icon.png +0 -0
  441. package/figma-desktop-bridge/manifest.json +67 -0
  442. package/figma-desktop-bridge/ui.html +2783 -0
  443. package/package.json +103 -0
@@ -0,0 +1,230 @@
1
+ /**
2
+ * Figma Annotations MCP Tools
3
+ * Tools for reading, writing, and managing design annotations on Figma nodes.
4
+ * Annotations are a Plugin API feature — requires Desktop Bridge plugin connection.
5
+ *
6
+ * Annotations are distinct from comments: they are node-level design specs that
7
+ * can pin specific properties (fills, width, typography, etc.) and support
8
+ * markdown-formatted labels. Designers use them to communicate animation timings,
9
+ * accessibility requirements, interaction specs, and other implementation details
10
+ * that don't fit in the description field.
11
+ */
12
+ import { z } from "zod";
13
+ import { createChildLogger } from "./logger.js";
14
+ const logger = createChildLogger({ component: "annotation-tools" });
15
+ // Valid AnnotationPropertyType values from the Figma Plugin API
16
+ // Sourced from @figma/plugin-typings — keep in sync with AnnotationPropertyType union
17
+ // Reference: https://developers.figma.com/docs/plugins/api/AnnotationProperty
18
+ const ANNOTATION_PROPERTY_TYPES = [
19
+ "width",
20
+ "height",
21
+ "maxWidth",
22
+ "minWidth",
23
+ "maxHeight",
24
+ "minHeight",
25
+ "fills",
26
+ "strokes",
27
+ "effects",
28
+ "strokeWeight",
29
+ "cornerRadius",
30
+ "textStyleId",
31
+ "textAlignHorizontal",
32
+ "fontFamily",
33
+ "fontStyle",
34
+ "fontSize",
35
+ "fontWeight",
36
+ "lineHeight",
37
+ "letterSpacing",
38
+ "itemSpacing",
39
+ "padding",
40
+ "layoutMode",
41
+ "alignItems",
42
+ "opacity",
43
+ "mainComponent",
44
+ "gridRowGap",
45
+ "gridColumnGap",
46
+ "gridRowCount",
47
+ "gridColumnCount",
48
+ "gridRowAnchorIndex",
49
+ "gridColumnAnchorIndex",
50
+ "gridRowSpan",
51
+ "gridColumnSpan",
52
+ ];
53
+ // Zod schema for annotation property
54
+ const annotationPropertySchema = z.object({
55
+ type: z
56
+ .enum(ANNOTATION_PROPERTY_TYPES)
57
+ .describe("Design property to pin (e.g., 'fills', 'width', 'fontSize')"),
58
+ });
59
+ // Zod schema for a single annotation
60
+ const annotationSchema = z.object({
61
+ label: z
62
+ .string()
63
+ .optional()
64
+ .describe("Plain text annotation label"),
65
+ labelMarkdown: z
66
+ .string()
67
+ .optional()
68
+ .describe("Rich text annotation label with markdown formatting. Supports bold, italic, links, lists, code, and headers."),
69
+ properties: z
70
+ .array(annotationPropertySchema)
71
+ .optional()
72
+ .describe("Design properties to pin to this annotation (e.g., fills, width, fontSize)"),
73
+ categoryId: z
74
+ .string()
75
+ .optional()
76
+ .describe("Annotation category ID. Use figma_get_annotation_categories to list available categories."),
77
+ });
78
+ // ============================================================================
79
+ // Tool Registration
80
+ // ============================================================================
81
+ export function registerAnnotationTools(server, getDesktopConnector) {
82
+ // -----------------------------------------------------------------------
83
+ // Tool: figma_get_annotations
84
+ // -----------------------------------------------------------------------
85
+ server.tool("figma_get_annotations", "Read annotations from a Figma node. Annotations are designer-authored specs attached to nodes — they can include notes (plain text or markdown), pinned design properties (fills, width, fontSize, etc.), and category labels. Use this to discover animation timings, interaction specs, accessibility requirements, and other implementation details that designers annotate directly on the design. Set include_children=true to get annotations from child nodes too (useful for full component documentation). Requires Desktop Bridge plugin.", {
86
+ nodeId: z
87
+ .string()
88
+ .describe("Node ID to read annotations from (e.g., '695:313')"),
89
+ include_children: z.preprocess((v) => (typeof v === "string" ? v === "true" : v), z.boolean().optional().default(false)).describe("Also read annotations from child nodes. Useful for getting all annotations within a component tree."),
90
+ depth: z.preprocess((v) => (typeof v === "string" ? Number(v) : v), z.number().optional().default(1)).describe("How many levels deep to traverse when include_children is true (default: 1, max recommended: 5)"),
91
+ }, async ({ nodeId, include_children = false, depth = 1 }) => {
92
+ try {
93
+ logger.info({ nodeId, include_children, depth }, "Getting annotations");
94
+ const connector = await getDesktopConnector();
95
+ const result = await connector.getAnnotations(nodeId, include_children, Math.min(depth, 10));
96
+ if (!result || (result.success === false)) {
97
+ throw new Error(result?.error || "Failed to get annotations");
98
+ }
99
+ // The result may come back as { success, data } (WebSocket) or directly as data
100
+ const data = result.data || result;
101
+ return {
102
+ content: [
103
+ {
104
+ type: "text",
105
+ text: JSON.stringify(data),
106
+ },
107
+ ],
108
+ };
109
+ }
110
+ catch (error) {
111
+ const message = error instanceof Error ? error.message : String(error);
112
+ logger.error({ error }, "Failed to get annotations");
113
+ return {
114
+ content: [
115
+ {
116
+ type: "text",
117
+ text: JSON.stringify({
118
+ error: "get_annotations_failed",
119
+ message: `Cannot get annotations. ${message}`,
120
+ hint: "Annotations require the Desktop Bridge plugin to be running in Figma.",
121
+ }),
122
+ },
123
+ ],
124
+ isError: true,
125
+ };
126
+ }
127
+ });
128
+ // -----------------------------------------------------------------------
129
+ // Tool: figma_set_annotations
130
+ // -----------------------------------------------------------------------
131
+ server.tool("figma_set_annotations", "Write or clear annotations on a Figma node. Annotations communicate design specs to developers — use them to document animation timings, easing curves, interaction behaviors, accessibility requirements, and implementation notes. Supports plain text labels, rich markdown labels, pinned design properties, and annotation categories. Pass an empty array to clear all annotations. Use mode='append' to add to existing annotations, or mode='replace' (default) to overwrite. Requires Desktop Bridge plugin. This operation is undoable in Figma (Cmd+Z).", {
132
+ nodeId: z
133
+ .string()
134
+ .describe("Node ID to write annotations to (e.g., '695:313')"),
135
+ annotations: z.preprocess((v) => {
136
+ if (typeof v === "string") {
137
+ try {
138
+ return JSON.parse(v);
139
+ }
140
+ catch {
141
+ return v;
142
+ }
143
+ }
144
+ return v;
145
+ }, z.array(annotationSchema)).describe("Array of annotations to set. Each annotation can have a label (plain or markdown), pinned properties, and a category. Pass an empty array [] to clear all annotations."),
146
+ mode: z
147
+ .enum(["replace", "append"])
148
+ .optional()
149
+ .default("replace")
150
+ .describe("'replace' (default) overwrites all existing annotations. 'append' adds new annotations while keeping existing ones."),
151
+ }, async ({ nodeId, annotations, mode = "replace" }) => {
152
+ try {
153
+ logger.info({ nodeId, count: annotations.length, mode }, "Setting annotations");
154
+ const connector = await getDesktopConnector();
155
+ const result = await connector.setAnnotations(nodeId, annotations, mode);
156
+ if (!result || (result.success === false)) {
157
+ throw new Error(result?.error || "Failed to set annotations");
158
+ }
159
+ const data = result.data || result;
160
+ return {
161
+ content: [
162
+ {
163
+ type: "text",
164
+ text: JSON.stringify({
165
+ success: true,
166
+ ...data,
167
+ note: "Annotations set successfully. This operation is undoable in Figma (Cmd+Z).",
168
+ }),
169
+ },
170
+ ],
171
+ };
172
+ }
173
+ catch (error) {
174
+ const message = error instanceof Error ? error.message : String(error);
175
+ logger.error({ error }, "Failed to set annotations");
176
+ return {
177
+ content: [
178
+ {
179
+ type: "text",
180
+ text: JSON.stringify({
181
+ error: "set_annotations_failed",
182
+ message: `Cannot set annotations. ${message}`,
183
+ hint: "Annotations require the Desktop Bridge plugin to be running in Figma.",
184
+ }),
185
+ },
186
+ ],
187
+ isError: true,
188
+ };
189
+ }
190
+ });
191
+ // -----------------------------------------------------------------------
192
+ // Tool: figma_get_annotation_categories
193
+ // -----------------------------------------------------------------------
194
+ server.tool("figma_get_annotation_categories", "List available annotation categories in the current Figma file. Categories group annotations by purpose (e.g., interactions, accessibility, development notes). Use the returned category IDs when creating annotations with figma_set_annotations. Requires Desktop Bridge plugin.", {}, async () => {
195
+ try {
196
+ logger.info("Getting annotation categories");
197
+ const connector = await getDesktopConnector();
198
+ const result = await connector.getAnnotationCategories();
199
+ if (!result || (result.success === false)) {
200
+ throw new Error(result?.error || "Failed to get annotation categories");
201
+ }
202
+ const data = result.data || result;
203
+ return {
204
+ content: [
205
+ {
206
+ type: "text",
207
+ text: JSON.stringify(data),
208
+ },
209
+ ],
210
+ };
211
+ }
212
+ catch (error) {
213
+ const message = error instanceof Error ? error.message : String(error);
214
+ logger.error({ error }, "Failed to get annotation categories");
215
+ return {
216
+ content: [
217
+ {
218
+ type: "text",
219
+ text: JSON.stringify({
220
+ error: "get_annotation_categories_failed",
221
+ message: `Cannot get annotation categories. ${message}`,
222
+ hint: "Annotation categories require the Desktop Bridge plugin to be running in Figma.",
223
+ }),
224
+ },
225
+ ],
226
+ isError: true,
227
+ };
228
+ }
229
+ });
230
+ }
@@ -0,0 +1,419 @@
1
+ /**
2
+ * Cloud WebSocket Connector
3
+ *
4
+ * Implements IFigmaConnector by routing commands through the PluginRelayDO
5
+ * Durable Object. Each method maps to a command sent via fetch() RPC to
6
+ * the relay, which forwards it to the Figma Desktop Bridge plugin over
7
+ * WebSocket.
8
+ *
9
+ * Structurally mirrors WebSocketConnector — same methods, different transport.
10
+ */
11
+ export class CloudWebSocketConnector {
12
+ constructor(relayStub) {
13
+ this.relayStub = relayStub;
14
+ }
15
+ async initialize() {
16
+ const res = await this.relayStub.fetch('https://relay/relay/status');
17
+ const status = await res.json();
18
+ if (!status.connected) {
19
+ throw new Error('No plugin connected to cloud relay. User must pair the Desktop Bridge plugin first (use figma_pair_plugin tool).');
20
+ }
21
+ }
22
+ getTransportType() {
23
+ return 'websocket';
24
+ }
25
+ // ============================================================================
26
+ // Core execution
27
+ // ============================================================================
28
+ async executeInPluginContext(code) {
29
+ return this.sendCommand('EXECUTE_CODE', { code, timeout: 5000 }, 7000);
30
+ }
31
+ async getVariablesFromPluginUI(fileKey) {
32
+ return this.sendCommand('GET_VARIABLES_DATA', {}, 10000);
33
+ }
34
+ async getVariables(fileKey) {
35
+ // IMPORTANT: bare try/catch with top-level `return`, NO inner IIFE.
36
+ // See issue #68 + the matching note in websocket-connector.ts. The plugin
37
+ // (code.js) wraps every EXECUTE_CODE payload in its own async IIFE; nesting
38
+ // another swallows the inner return and silently drops the variables.
39
+ const code = `
40
+ try {
41
+ if (typeof figma === 'undefined') {
42
+ throw new Error('Figma API not available in this context');
43
+ }
44
+ const variables = await figma.variables.getLocalVariablesAsync();
45
+ const collections = await figma.variables.getLocalVariableCollectionsAsync();
46
+ return {
47
+ success: true,
48
+ timestamp: Date.now(),
49
+ fileMetadata: { fileName: figma.root.name, fileKey: figma.fileKey || null },
50
+ 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 }; }),
51
+ variableCollections: collections.map(function(c) { return { id: c.id, name: c.name, key: c.key, modes: c.modes, defaultModeId: c.defaultModeId, variableIds: c.variableIds }; })
52
+ };
53
+ } catch (error) {
54
+ return { success: false, error: error.message };
55
+ }
56
+ `;
57
+ return this.sendCommand('EXECUTE_CODE', { code, timeout: 30000 }, 32000);
58
+ }
59
+ async executeCodeViaUI(code, timeoutMs = 5000) {
60
+ return this.sendCommand('EXECUTE_CODE', { code, timeout: timeoutMs }, timeoutMs + 2000);
61
+ }
62
+ // ============================================================================
63
+ // Variable operations
64
+ // ============================================================================
65
+ async updateVariable(variableId, modeId, value) {
66
+ return this.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.sendCommand('CREATE_VARIABLE', params);
79
+ }
80
+ async deleteVariable(variableId) {
81
+ return this.sendCommand('DELETE_VARIABLE', { variableId });
82
+ }
83
+ async refreshVariables() {
84
+ return this.sendCommand('REFRESH_VARIABLES', {}, 300000);
85
+ }
86
+ async renameVariable(variableId, newName) {
87
+ const result = await this.sendCommand('RENAME_VARIABLE', { variableId, newName });
88
+ if (!result.oldName && result.variable?.oldName)
89
+ result.oldName = result.variable.oldName;
90
+ return result;
91
+ }
92
+ async setVariableDescription(variableId, description) {
93
+ return this.sendCommand('SET_VARIABLE_DESCRIPTION', { variableId, description });
94
+ }
95
+ // ============================================================================
96
+ // Mode operations
97
+ // ============================================================================
98
+ async addMode(collectionId, modeName) {
99
+ return this.sendCommand('ADD_MODE', { collectionId, modeName });
100
+ }
101
+ async renameMode(collectionId, modeId, newName) {
102
+ const result = await this.sendCommand('RENAME_MODE', { collectionId, modeId, newName });
103
+ if (!result.oldName && result.collection?.oldName)
104
+ result.oldName = result.collection.oldName;
105
+ return result;
106
+ }
107
+ // ============================================================================
108
+ // Collection operations
109
+ // ============================================================================
110
+ async createVariableCollection(name, options) {
111
+ const params = { name };
112
+ if (options) {
113
+ if (options.initialModeName)
114
+ params.initialModeName = options.initialModeName;
115
+ if (options.additionalModes)
116
+ params.additionalModes = options.additionalModes;
117
+ }
118
+ return this.sendCommand('CREATE_VARIABLE_COLLECTION', params);
119
+ }
120
+ async deleteVariableCollection(collectionId) {
121
+ return this.sendCommand('DELETE_VARIABLE_COLLECTION', { collectionId });
122
+ }
123
+ // ============================================================================
124
+ // Component operations
125
+ // ============================================================================
126
+ async getComponentFromPluginUI(nodeId) {
127
+ return this.sendCommand('GET_COMPONENT', { nodeId }, 10000);
128
+ }
129
+ async getLocalComponents() {
130
+ return this.sendCommand('GET_LOCAL_COMPONENTS', {}, 300000);
131
+ }
132
+ async setNodeDescription(nodeId, description, descriptionMarkdown) {
133
+ return this.sendCommand('SET_NODE_DESCRIPTION', { nodeId, description, descriptionMarkdown });
134
+ }
135
+ // ============================================================================
136
+ // Annotation operations
137
+ // ============================================================================
138
+ async getAnnotations(nodeId, includeChildren, depth) {
139
+ return this.sendCommand('GET_ANNOTATIONS', { nodeId, includeChildren, depth }, 10000);
140
+ }
141
+ async setAnnotations(nodeId, annotations, mode) {
142
+ return this.sendCommand('SET_ANNOTATIONS', { nodeId, annotations, mode: mode || 'replace' });
143
+ }
144
+ async getAnnotationCategories() {
145
+ return this.sendCommand('GET_ANNOTATION_CATEGORIES', {}, 5000);
146
+ }
147
+ async deepGetComponent(nodeId, depth) {
148
+ return this.sendCommand('DEEP_GET_COMPONENT', { nodeId, depth: depth || 10 }, 30000);
149
+ }
150
+ async analyzeComponentSet(nodeId) {
151
+ return this.sendCommand('ANALYZE_COMPONENT_SET', { nodeId }, 30000);
152
+ }
153
+ async addComponentProperty(nodeId, propertyName, type, defaultValue, options) {
154
+ const params = { nodeId, propertyName, propertyType: type, defaultValue };
155
+ if (options?.preferredValues)
156
+ params.preferredValues = options.preferredValues;
157
+ if (options?.description)
158
+ params.description = options.description;
159
+ return this.sendCommand('ADD_COMPONENT_PROPERTY', params);
160
+ }
161
+ async editComponentProperty(nodeId, propertyName, newValue) {
162
+ return this.sendCommand('EDIT_COMPONENT_PROPERTY', { nodeId, propertyName, newValue });
163
+ }
164
+ async deleteComponentProperty(nodeId, propertyName) {
165
+ return this.sendCommand('DELETE_COMPONENT_PROPERTY', { nodeId, propertyName });
166
+ }
167
+ async instantiateComponent(componentKey, options) {
168
+ const params = { componentKey };
169
+ if (options) {
170
+ if (options.nodeId)
171
+ params.nodeId = options.nodeId;
172
+ if (options.position)
173
+ params.position = options.position;
174
+ if (options.size)
175
+ params.size = options.size;
176
+ if (options.overrides)
177
+ params.overrides = options.overrides;
178
+ if (options.variant)
179
+ params.variant = options.variant;
180
+ if (options.parentId)
181
+ params.parentId = options.parentId;
182
+ }
183
+ return this.sendCommand('INSTANTIATE_COMPONENT', params);
184
+ }
185
+ async createComponentSet(params) {
186
+ // Timeout scales with variant count — the plugin builds all variants in
187
+ // one uncancellable pass, so a fixed 30s ceiling on big matrices reports
188
+ // failure while the set still gets created (retry → duplicates).
189
+ // Mirrors componentSetTimeoutMs in websocket-connector.ts (not imported:
190
+ // that module pulls the Node 'ws' stack into the Workers bundle).
191
+ let variantCount = 1;
192
+ if (params.componentIds?.length) {
193
+ variantCount = params.componentIds.length;
194
+ }
195
+ else if (params.properties) {
196
+ for (const values of Object.values(params.properties)) {
197
+ variantCount *= Math.max(1, values?.length ?? 1);
198
+ }
199
+ }
200
+ const timeout = Math.min(120000, Math.max(30000, variantCount * 1200)) + 5000;
201
+ return this.sendCommand('CREATE_COMPONENT_SET', params, timeout);
202
+ }
203
+ // ============================================================================
204
+ // Slot operations
205
+ // ============================================================================
206
+ async createSlot(nodeId, options) {
207
+ return this.sendCommand('CREATE_SLOT', { nodeId, ...options });
208
+ }
209
+ async getSlots(nodeId) {
210
+ return this.sendCommand('GET_SLOTS', { nodeId });
211
+ }
212
+ async appendToSlot(params) {
213
+ return this.sendCommand('APPEND_TO_SLOT', params);
214
+ }
215
+ async resetSlot(params) {
216
+ return this.sendCommand('RESET_SLOT', params);
217
+ }
218
+ // ============================================================================
219
+ // Node manipulation
220
+ // ============================================================================
221
+ async resizeNode(nodeId, width, height, withConstraints = true) {
222
+ return this.sendCommand('RESIZE_NODE', { nodeId, width, height, withConstraints });
223
+ }
224
+ async moveNode(nodeId, x, y) {
225
+ return this.sendCommand('MOVE_NODE', { nodeId, x, y });
226
+ }
227
+ async setNodeFills(nodeId, fills) {
228
+ return this.sendCommand('SET_NODE_FILLS', { nodeId, fills });
229
+ }
230
+ async setNodeStrokes(nodeId, strokes, strokeWeight) {
231
+ const params = { nodeId, strokes };
232
+ if (strokeWeight !== undefined)
233
+ params.strokeWeight = strokeWeight;
234
+ return this.sendCommand('SET_NODE_STROKES', params);
235
+ }
236
+ async setNodeOpacity(nodeId, opacity) {
237
+ return this.sendCommand('SET_NODE_OPACITY', { nodeId, opacity });
238
+ }
239
+ async setNodeCornerRadius(nodeId, radius) {
240
+ return this.sendCommand('SET_NODE_CORNER_RADIUS', { nodeId, radius });
241
+ }
242
+ async cloneNode(nodeId) {
243
+ return this.sendCommand('CLONE_NODE', { nodeId });
244
+ }
245
+ async deleteNode(nodeId) {
246
+ return this.sendCommand('DELETE_NODE', { nodeId });
247
+ }
248
+ async renameNode(nodeId, newName) {
249
+ return this.sendCommand('RENAME_NODE', { nodeId, newName });
250
+ }
251
+ async setTextContent(nodeId, characters, options) {
252
+ const params = { nodeId, text: characters };
253
+ if (options) {
254
+ if (options.fontSize)
255
+ params.fontSize = options.fontSize;
256
+ if (options.fontWeight)
257
+ params.fontWeight = options.fontWeight;
258
+ if (options.fontFamily)
259
+ params.fontFamily = options.fontFamily;
260
+ if (options.fontStyle)
261
+ params.fontStyle = options.fontStyle;
262
+ }
263
+ return this.sendCommand('SET_TEXT_CONTENT', params);
264
+ }
265
+ async createChildNode(parentId, nodeType, properties) {
266
+ return this.sendCommand('CREATE_CHILD_NODE', { parentId, nodeType, properties: properties || {} });
267
+ }
268
+ // ============================================================================
269
+ // Screenshot & instance properties
270
+ // ============================================================================
271
+ async captureScreenshot(nodeId, options) {
272
+ const params = { nodeId };
273
+ if (options?.format)
274
+ params.format = options.format;
275
+ if (options?.scale)
276
+ params.scale = options.scale;
277
+ return this.sendCommand('CAPTURE_SCREENSHOT', params, 30000);
278
+ }
279
+ async setInstanceProperties(nodeId, properties) {
280
+ return this.sendCommand('SET_INSTANCE_PROPERTIES', { nodeId, properties });
281
+ }
282
+ // ============================================================================
283
+ // Image fill
284
+ // ============================================================================
285
+ async setImageFill(nodeIds, imageData, scaleMode = 'FILL') {
286
+ return this.sendCommand('SET_IMAGE_FILL', { nodeIds, imageData, scaleMode }, 60000);
287
+ }
288
+ // ============================================================================
289
+ // Design lint
290
+ // ============================================================================
291
+ async lintDesign(nodeId, rules, maxDepth, maxFindings) {
292
+ const params = {};
293
+ if (nodeId)
294
+ params.nodeId = nodeId;
295
+ if (rules)
296
+ params.rules = rules;
297
+ if (maxDepth !== undefined)
298
+ params.maxDepth = maxDepth;
299
+ if (maxFindings !== undefined)
300
+ params.maxFindings = maxFindings;
301
+ return this.sendCommand('LINT_DESIGN', params, 120000);
302
+ }
303
+ // ============================================================================
304
+ // Component accessibility audit
305
+ // ============================================================================
306
+ async auditComponentAccessibility(nodeId, targetSize) {
307
+ const params = {};
308
+ if (nodeId)
309
+ params.nodeId = nodeId;
310
+ if (targetSize !== undefined)
311
+ params.targetSize = targetSize;
312
+ return this.sendCommand('AUDIT_COMPONENT_ACCESSIBILITY', params, 120000);
313
+ }
314
+ // ============================================================================
315
+ // FigJam operations
316
+ // ============================================================================
317
+ async createSticky(params) {
318
+ return this.sendCommand('CREATE_STICKY', params);
319
+ }
320
+ async createStickies(params) {
321
+ return this.sendCommand('CREATE_STICKIES', params, 30000);
322
+ }
323
+ async createConnector(params) {
324
+ return this.sendCommand('CREATE_CONNECTOR', params);
325
+ }
326
+ async createShapeWithText(params) {
327
+ return this.sendCommand('CREATE_SHAPE_WITH_TEXT', params);
328
+ }
329
+ async createSection(params) {
330
+ return this.sendCommand('CREATE_SECTION', params);
331
+ }
332
+ async createTable(params) {
333
+ return this.sendCommand('CREATE_TABLE', params, 30000);
334
+ }
335
+ async createCodeBlock(params) {
336
+ return this.sendCommand('CREATE_CODE_BLOCK', params);
337
+ }
338
+ async getBoardContents(params) {
339
+ return this.sendCommand('GET_BOARD_CONTENTS', params, 30000);
340
+ }
341
+ async getConnections() {
342
+ return this.sendCommand('GET_CONNECTIONS', {}, 15000);
343
+ }
344
+ // ============================================================================
345
+ // Slides operations
346
+ // ============================================================================
347
+ async listSlides() {
348
+ return this.sendCommand('LIST_SLIDES', {}, 10000);
349
+ }
350
+ async getSlideContent(params) {
351
+ return this.sendCommand('GET_SLIDE_CONTENT', params, 10000);
352
+ }
353
+ async createSlide(params) {
354
+ return this.sendCommand('CREATE_SLIDE', params, 10000);
355
+ }
356
+ async deleteSlide(params) {
357
+ return this.sendCommand('DELETE_SLIDE', params, 5000);
358
+ }
359
+ async duplicateSlide(params) {
360
+ return this.sendCommand('DUPLICATE_SLIDE', params, 5000);
361
+ }
362
+ async getSlideGrid() {
363
+ return this.sendCommand('GET_SLIDE_GRID', {}, 10000);
364
+ }
365
+ async reorderSlides(params) {
366
+ return this.sendCommand('REORDER_SLIDES', params, 15000);
367
+ }
368
+ async setSlideTransition(params) {
369
+ return this.sendCommand('SET_SLIDE_TRANSITION', params, 5000);
370
+ }
371
+ async getSlideTransition(params) {
372
+ return this.sendCommand('GET_SLIDE_TRANSITION', params, 5000);
373
+ }
374
+ async setSlidesViewMode(params) {
375
+ return this.sendCommand('SET_SLIDES_VIEW_MODE', params, 5000);
376
+ }
377
+ async getFocusedSlide() {
378
+ return this.sendCommand('GET_FOCUSED_SLIDE', {}, 5000);
379
+ }
380
+ async focusSlide(params) {
381
+ return this.sendCommand('FOCUS_SLIDE', params, 5000);
382
+ }
383
+ async skipSlide(params) {
384
+ return this.sendCommand('SKIP_SLIDE', params, 5000);
385
+ }
386
+ async addTextToSlide(params) {
387
+ return this.sendCommand('ADD_TEXT_TO_SLIDE', params, 10000);
388
+ }
389
+ async addShapeToSlide(params) {
390
+ return this.sendCommand('ADD_SHAPE_TO_SLIDE', params, 5000);
391
+ }
392
+ async setSlideBackground(params) {
393
+ return this.sendCommand('SET_SLIDE_BACKGROUND', params, 5000);
394
+ }
395
+ async getTextStyles() {
396
+ return this.sendCommand('GET_TEXT_STYLES', {}, 5000);
397
+ }
398
+ // ============================================================================
399
+ // Cache management (no-op for cloud relay)
400
+ // ============================================================================
401
+ clearFrameCache() {
402
+ // No frame cache in cloud relay mode
403
+ }
404
+ // ============================================================================
405
+ // Transport — fetch-based RPC to the relay DO
406
+ // ============================================================================
407
+ async sendCommand(method, params = {}, timeoutMs = 15000) {
408
+ const res = await this.relayStub.fetch('https://relay/relay/command', {
409
+ method: 'POST',
410
+ headers: { 'Content-Type': 'application/json' },
411
+ body: JSON.stringify({ method, params, timeoutMs }),
412
+ });
413
+ const data = await res.json();
414
+ if (data.error) {
415
+ throw new Error(data.error);
416
+ }
417
+ return data.result;
418
+ }
419
+ }