@jxsuite/studio 2.0.0 → 2.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 (419) hide show
  1. package/canvas.html +21 -0
  2. package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
  3. package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
  4. package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
  5. package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
  6. package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
  7. package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
  8. package/dist/chunks/content-source-34gnkbnn.js +38 -0
  9. package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
  10. package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
  11. package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
  12. package/dist/chunks/extension-sections-6mqydz35.js +301 -0
  13. package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
  14. package/dist/chunks/files-8kn321h1.js +70 -0
  15. package/dist/chunks/files-8kn321h1.js.map +9 -0
  16. package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
  17. package/dist/chunks/git-panel-tjbr191d.js +51 -0
  18. package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
  19. package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
  20. package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
  21. package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
  22. package/dist/chunks/layers-panel-87pb25km.js +58 -0
  23. package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
  24. package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
  25. package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
  26. package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
  27. package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
  28. package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
  29. package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
  30. package/dist/chunks/right-panel-zpdxd98t.js +37 -0
  31. package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
  32. package/dist/chunks/section-registry-zmckaxf4.js +30 -0
  33. package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
  34. package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
  35. package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
  36. package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
  37. package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
  38. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
  39. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
  40. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
  41. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
  42. package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
  43. package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
  44. package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
  45. package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
  46. package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
  47. package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
  48. package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
  49. package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
  50. package/dist/chunks/studio-41exgzhq.js +6690 -0
  51. package/dist/chunks/studio-41exgzhq.js.map +38 -0
  52. package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
  53. package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
  54. package/dist/chunks/studio-50k77cca.js +1787 -0
  55. package/dist/chunks/studio-50k77cca.js.map +18 -0
  56. package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
  57. package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
  58. package/dist/chunks/studio-6f0am8f2.js +53 -0
  59. package/dist/chunks/studio-6f0am8f2.js.map +10 -0
  60. package/dist/chunks/studio-6nmjc5qk.js +7002 -0
  61. package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
  62. package/dist/chunks/studio-7afd21nw.js +67 -0
  63. package/dist/chunks/studio-7afd21nw.js.map +10 -0
  64. package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
  65. package/dist/chunks/studio-7bmdvzne.js.map +10 -0
  66. package/dist/chunks/studio-8jpzqk5s.js +128 -0
  67. package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
  68. package/dist/chunks/studio-94m77tgk.js +1482 -0
  69. package/dist/chunks/studio-94m77tgk.js.map +13 -0
  70. package/dist/chunks/studio-9je6w5sq.js +1000 -0
  71. package/dist/chunks/studio-9je6w5sq.js.map +16 -0
  72. package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
  73. package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
  74. package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
  75. package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
  76. package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
  77. package/dist/chunks/studio-bw5dz6km.js +608 -0
  78. package/dist/chunks/studio-bw5dz6km.js.map +21 -0
  79. package/dist/chunks/studio-c6s5getc.js +4232 -0
  80. package/dist/chunks/studio-c6s5getc.js.map +39 -0
  81. package/dist/chunks/studio-cjm7fdjf.js +451 -0
  82. package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
  83. package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
  84. package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
  85. package/dist/chunks/studio-dg7zyt5x.js +28 -0
  86. package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
  87. package/dist/chunks/studio-dzcyvvvz.js +166 -0
  88. package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
  89. package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
  90. package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
  91. package/dist/chunks/studio-f12h6177.js +411 -0
  92. package/dist/chunks/studio-f12h6177.js.map +13 -0
  93. package/dist/chunks/studio-hbp1s8m9.js +1817 -0
  94. package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
  95. package/dist/chunks/studio-k2sxjph5.js +15295 -0
  96. package/dist/chunks/studio-k2sxjph5.js.map +235 -0
  97. package/dist/chunks/studio-myje51t3.js +385 -0
  98. package/dist/chunks/studio-myje51t3.js.map +12 -0
  99. package/dist/chunks/studio-na6rwzhw.js +353 -0
  100. package/dist/chunks/studio-na6rwzhw.js.map +11 -0
  101. package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
  102. package/dist/chunks/studio-p471gg5n.js.map +14 -0
  103. package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
  104. package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
  105. package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
  106. package/dist/chunks/studio-sas7mt3k.js +75 -0
  107. package/dist/chunks/studio-sas7mt3k.js.map +10 -0
  108. package/dist/chunks/studio-t5wqwzdh.js +74 -0
  109. package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
  110. package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
  111. package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
  112. package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
  113. package/dist/chunks/studio-tr20m8g8.js.map +9 -0
  114. package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
  115. package/dist/chunks/studio-v96qfnww.js.map +54 -0
  116. package/dist/chunks/studio-vcetc91k.js +659 -0
  117. package/dist/chunks/studio-vcetc91k.js.map +10 -0
  118. package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
  119. package/dist/chunks/studio-vmymjefp.js.map +98 -0
  120. package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
  121. package/dist/chunks/studio-x9hmy5kr.js +390 -0
  122. package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
  123. package/dist/chunks/studio-xa0ce0n7.js +335 -0
  124. package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
  125. package/dist/chunks/studio-xm3dbxvn.js +378 -0
  126. package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
  127. package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
  128. package/dist/chunks/studio-zv37yrfa.js +1054 -0
  129. package/dist/chunks/studio-zv37yrfa.js.map +13 -0
  130. package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
  131. package/dist/chunks/ws-client-654ts66j.js.map +11 -0
  132. package/dist/iframe-entry.js +668 -230
  133. package/dist/studio.js +23711 -35185
  134. package/index.html +35 -4685
  135. package/package.json +17 -15
  136. package/src/about/about-modal.ts +42 -11
  137. package/src/browse/library-commands.ts +240 -0
  138. package/src/browse/library-layouts.ts +369 -0
  139. package/src/browse/library-model.ts +396 -0
  140. package/src/browse/library-pane.ts +1049 -0
  141. package/src/browse/library-preview.ts +252 -0
  142. package/src/browse/library-source.ts +150 -0
  143. package/src/canvas/canvas-helpers.ts +33 -9
  144. package/src/canvas/canvas-live-render.ts +45 -29
  145. package/src/canvas/canvas-patcher.ts +151 -31
  146. package/src/canvas/canvas-perf.ts +46 -7
  147. package/src/canvas/canvas-render.ts +1092 -220
  148. package/src/canvas/canvas-surface.ts +240 -0
  149. package/src/canvas/canvas-utils.ts +1166 -124
  150. package/src/canvas/iframe-drop.ts +2 -1
  151. package/src/canvas/iframe-entry.ts +241 -4
  152. package/src/canvas/iframe-host.ts +1226 -143
  153. package/src/canvas/iframe-inline-edit.ts +31 -0
  154. package/src/canvas/iframe-interaction.ts +76 -16
  155. package/src/canvas/iframe-keys.ts +107 -45
  156. package/src/canvas/iframe-overlay.ts +38 -1
  157. package/src/canvas/iframe-protocol.ts +137 -2
  158. package/src/canvas/iframe-render.ts +70 -2
  159. package/src/canvas/iframe-slash.ts +6 -0
  160. package/src/canvas/path-mapping.ts +56 -6
  161. package/src/canvas/surface-registry.ts +292 -0
  162. package/src/collab/collab-commands.ts +244 -0
  163. package/src/collab/collab-session.ts +198 -32
  164. package/src/collab/collab-state.ts +28 -2
  165. package/src/collab/presence-chips.ts +100 -9
  166. package/src/commands/active-registry.ts +42 -0
  167. package/src/commands/app-commands.ts +176 -0
  168. package/src/commands/budget.ts +158 -0
  169. package/src/commands/command-args.ts +253 -0
  170. package/src/commands/context.ts +387 -0
  171. package/src/commands/defaults.ts +580 -0
  172. package/src/commands/keymap.ts +571 -0
  173. package/src/commands/levels.ts +345 -0
  174. package/src/commands/live-context.ts +193 -0
  175. package/src/commands/reference.ts +227 -0
  176. package/src/commands/registry.ts +293 -0
  177. package/src/component-props.ts +3 -2
  178. package/src/content/draft-state.ts +106 -0
  179. package/src/content/entry-commands.ts +282 -0
  180. package/src/content/entry-editor.ts +327 -0
  181. package/src/content/entry-fields.ts +116 -0
  182. package/src/content/entry-model.ts +175 -0
  183. package/src/editor/canvas-context-menu.ts +17 -11
  184. package/src/editor/canvas-slash-bridge.ts +11 -4
  185. package/src/editor/context-menu.ts +804 -204
  186. package/src/editor/convert-to-component.ts +31 -10
  187. package/src/editor/convert-to-repeater.ts +3 -2
  188. package/src/editor/inline-edit-apply.ts +5 -5
  189. package/src/editor/inline-edit.ts +86 -50
  190. package/src/editor/insert-zone-action.ts +1 -1
  191. package/src/editor/shortcuts.ts +1043 -329
  192. package/src/editor/slash-menu.ts +1 -0
  193. package/src/files/elements.ts +166 -0
  194. package/src/files/file-ops.ts +178 -31
  195. package/src/files/files.ts +898 -268
  196. package/src/files/fs-events.ts +21 -0
  197. package/src/files/media-meta.ts +203 -0
  198. package/src/files/media-paths.ts +141 -0
  199. package/src/files/media-upload.ts +7 -3
  200. package/src/files/media-usage.ts +189 -0
  201. package/src/github/github-auth.ts +235 -33
  202. package/src/github/github-publish.ts +80 -21
  203. package/src/grid/grid-controller.ts +152 -12
  204. package/src/grid/grid-layout.ts +225 -20
  205. package/src/grid/grid-open.ts +120 -0
  206. package/src/grid/grid-panel.ts +554 -39
  207. package/src/grid/grid-source.ts +27 -1
  208. package/src/grid/redirects-grid.ts +599 -0
  209. package/src/grid/redirects.ts +398 -0
  210. package/src/grid/sources/content-source.ts +108 -2
  211. package/src/i18n/i18n-commands.ts +322 -0
  212. package/src/new-project/add-repo-modal.ts +8 -10
  213. package/src/new-project/import-tab.ts +34 -9
  214. package/src/new-project/location-fields.ts +9 -1
  215. package/src/new-project/new-project-modal.ts +270 -262
  216. package/src/packages/jxsuite-update.ts +97 -48
  217. package/src/packages/pull-package-sync.ts +18 -9
  218. package/src/page-params.ts +2 -1
  219. package/src/panels/activity-bar.ts +152 -91
  220. package/src/panels/activity-panel.ts +481 -0
  221. package/src/panels/ai-chat/chat-markdown.ts +8 -3
  222. package/src/panels/ai-chat/chat-view.ts +245 -18
  223. package/src/panels/ai-chat/composer.ts +31 -5
  224. package/src/panels/ai-chat/sessions-view.ts +17 -10
  225. package/src/panels/ai-panel.ts +279 -120
  226. package/src/panels/block-action-bar.ts +1115 -224
  227. package/src/panels/bottom-dock.ts +337 -0
  228. package/src/panels/canvas-dnd-bridge.ts +37 -8
  229. package/src/panels/chat-panel.ts +29 -12
  230. package/src/panels/data-explorer.ts +254 -112
  231. package/src/panels/data-grid.ts +10 -4
  232. package/src/panels/dnd.ts +28 -51
  233. package/src/panels/editors.ts +434 -107
  234. package/src/panels/elements-panel.ts +66 -2
  235. package/src/panels/empty-state.ts +112 -0
  236. package/src/panels/events-panel.ts +596 -82
  237. package/src/panels/formula-workspace.ts +408 -218
  238. package/src/panels/frontmatter-fields.ts +51 -10
  239. package/src/panels/frontmatter-panel.ts +357 -79
  240. package/src/panels/git-panel.ts +375 -164
  241. package/src/panels/head-panel.ts +791 -85
  242. package/src/panels/i18n-panel.ts +592 -0
  243. package/src/panels/imports-panel.ts +95 -85
  244. package/src/panels/jump-bar.ts +584 -0
  245. package/src/panels/layers-panel.ts +1106 -328
  246. package/src/panels/left-panel.ts +109 -204
  247. package/src/panels/navigator-panels.ts +131 -0
  248. package/src/panels/overlays.ts +7 -2
  249. package/src/panels/pane-context.ts +1477 -0
  250. package/src/panels/pane-grid.ts +406 -0
  251. package/src/panels/panel-registry.ts +340 -0
  252. package/src/panels/panel-scheduler.ts +75 -0
  253. package/src/panels/problems-panel.ts +234 -0
  254. package/src/panels/properties-panel.ts +946 -1139
  255. package/src/panels/provenance.ts +258 -0
  256. package/src/panels/quick-search.ts +791 -122
  257. package/src/panels/right-panel.ts +228 -102
  258. package/src/panels/seo-modal.ts +395 -0
  259. package/src/panels/settings-pane.ts +203 -0
  260. package/src/panels/signals-panel.ts +354 -137
  261. package/src/panels/statement-editor.ts +41 -25
  262. package/src/panels/statusbar.ts +342 -106
  263. package/src/panels/style-panel.ts +974 -463
  264. package/src/panels/style-utils.ts +3 -3
  265. package/src/panels/stylebook-doc.ts +4 -2
  266. package/src/panels/stylebook-layers-panel.ts +3 -2
  267. package/src/panels/stylebook-panel.ts +51 -26
  268. package/src/panels/tab-strip.ts +1058 -78
  269. package/src/panels/target-line.ts +274 -0
  270. package/src/panels/toolbar.ts +631 -484
  271. package/src/panels/welcome-screen.ts +301 -198
  272. package/src/platform-errors.ts +26 -3
  273. package/src/platform.ts +96 -2
  274. package/src/platforms/cloud.ts +71 -8
  275. package/src/platforms/devserver.ts +92 -29
  276. package/src/publish/deploy-checklist.ts +383 -0
  277. package/src/publish/pages-service.ts +10 -1
  278. package/src/publish/publish-commands.ts +218 -0
  279. package/src/publish/publish-panel.ts +110 -16
  280. package/src/recent-projects.ts +3 -2
  281. package/src/services/a11y-report.ts +505 -0
  282. package/src/services/ai-models.ts +75 -2
  283. package/src/services/ai-project-tools.ts +29 -10
  284. package/src/services/ai-system-prompt.ts +53 -14
  285. package/src/services/ai-tools.ts +39 -3
  286. package/src/services/ai-writes.ts +154 -0
  287. package/src/services/announce.ts +97 -0
  288. package/src/services/automation.ts +424 -175
  289. package/src/services/cem-export.ts +9 -4
  290. package/src/services/clock.ts +61 -0
  291. package/src/services/document-assistant.ts +36 -8
  292. package/src/services/idle.ts +179 -0
  293. package/src/services/import-client.ts +26 -0
  294. package/src/services/monaco-buffer.ts +627 -0
  295. package/src/services/monaco-lazy.ts +36 -0
  296. package/src/services/notify.ts +271 -0
  297. package/src/services/profile.ts +155 -0
  298. package/src/services/references.ts +0 -0
  299. package/src/services/token-lint.ts +3 -2
  300. package/src/services/tool-executor.ts +53 -7
  301. package/src/services/trusted-types.ts +123 -0
  302. package/src/settings/contexts-section.ts +427 -0
  303. package/src/settings/contributed-section.ts +149 -11
  304. package/src/settings/css-vars-editor.ts +306 -349
  305. package/src/settings/defs-editor.ts +93 -34
  306. package/src/settings/dependencies-editor.ts +7 -7
  307. package/src/settings/extension-sections.ts +37 -5
  308. package/src/settings/general-settings.ts +204 -121
  309. package/src/settings/locales-section.ts +347 -0
  310. package/src/settings/preferences-accounts.ts +140 -0
  311. package/src/settings/preferences-dialog.ts +620 -0
  312. package/src/settings/preferences-keymap.ts +270 -0
  313. package/src/settings/project-sections.ts +260 -0
  314. package/src/settings/section-registry.ts +169 -0
  315. package/src/settings/settings-document.ts +385 -0
  316. package/src/shell.ts +1549 -0
  317. package/src/site-context.ts +45 -20
  318. package/src/state.ts +14 -275
  319. package/src/store.ts +88 -43
  320. package/src/studio.ts +790 -346
  321. package/src/style/live-preview.ts +36 -0
  322. package/src/style/project-styles.ts +349 -0
  323. package/src/style/token-ref.ts +123 -0
  324. package/src/tabs/patch-ops.ts +16 -4
  325. package/src/tabs/project-config.ts +416 -0
  326. package/src/tabs/selection.ts +323 -0
  327. package/src/tabs/tab.ts +182 -47
  328. package/src/tabs/transact.ts +209 -28
  329. package/src/types.ts +68 -13
  330. package/src/ui/ai-credentials-form.ts +39 -35
  331. package/src/ui/ai-managed-connect.ts +113 -0
  332. package/src/ui/dynamic-slot.ts +224 -81
  333. package/src/ui/expression-editor.ts +71 -63
  334. package/src/ui/field-input.ts +4 -6
  335. package/src/ui/field-row.ts +215 -38
  336. package/src/ui/form-controls.ts +194 -7
  337. package/src/ui/layers.ts +492 -69
  338. package/src/ui/media-picker.ts +115 -25
  339. package/src/ui/panel-resize.ts +109 -91
  340. package/src/ui/progress-modal.ts +131 -50
  341. package/src/ui/regions.ts +462 -0
  342. package/src/ui/schema-form.ts +229 -45
  343. package/src/ui/spectrum.ts +24 -8
  344. package/src/ui/timing.ts +49 -0
  345. package/src/ui/value-selector.ts +20 -0
  346. package/src/ui/value-source.ts +348 -0
  347. package/src/ui/virtual-window.ts +400 -0
  348. package/src/utils/edit-display.ts +3 -2
  349. package/src/utils/inherited-style.ts +67 -37
  350. package/src/view.ts +64 -78
  351. package/src/workspace/pane-derive.ts +1258 -0
  352. package/src/workspace/session.ts +317 -0
  353. package/src/workspace/workspace.ts +1345 -23
  354. package/styles/canvas.css +653 -0
  355. package/styles/forced-colors.css +106 -0
  356. package/styles/inspector.css +1454 -0
  357. package/styles/overlays.css +2704 -0
  358. package/styles/panels.css +1701 -0
  359. package/styles/shell.css +1423 -0
  360. package/styles/tokens.css +151 -0
  361. package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
  362. package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
  363. package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
  364. package/dist/chunks/files-02zn5y24.js +0 -50
  365. package/dist/chunks/files-02zn5y24.js.map +0 -9
  366. package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
  367. package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
  368. package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
  369. package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
  370. package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
  371. package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
  372. package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
  373. package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
  374. package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
  375. package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
  376. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
  377. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
  378. package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
  379. package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
  380. package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
  381. package/dist/chunks/studio-568nx4t5.js +0 -469
  382. package/dist/chunks/studio-568nx4t5.js.map +0 -14
  383. package/dist/chunks/studio-9smfzqhc.js +0 -19
  384. package/dist/chunks/studio-9smfzqhc.js.map +0 -10
  385. package/dist/chunks/studio-asvf0j9e.js +0 -429
  386. package/dist/chunks/studio-asvf0j9e.js.map +0 -13
  387. package/dist/chunks/studio-d77qm3pk.js +0 -3427
  388. package/dist/chunks/studio-d77qm3pk.js.map +0 -26
  389. package/dist/chunks/studio-j6gqyjf4.js +0 -1854
  390. package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
  391. package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
  392. package/dist/chunks/studio-qkvt37c0.js.map +0 -9
  393. package/dist/chunks/studio-rq0vxb19.js +0 -3744
  394. package/dist/chunks/studio-rq0vxb19.js.map +0 -22
  395. package/dist/chunks/studio-wd6ewdvd.js +0 -853
  396. package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
  397. package/dist/chunks/studio-xq0t7n5t.js +0 -140
  398. package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
  399. package/dist/chunks/studio-xze4zrs1.js.map +0 -10
  400. package/dist/chunks/studio-ygzav7z5.js.map +0 -46
  401. package/dist/chunks/studio-zmy7241e.js +0 -399
  402. package/dist/chunks/studio-zmy7241e.js.map +0 -12
  403. package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
  404. package/src/browse/browse-modal.ts +0 -69
  405. package/src/browse/browse.ts +0 -904
  406. package/src/canvas/canvas-diff.ts +0 -216
  407. package/src/canvas/nested-site-style.ts +0 -58
  408. package/src/new-project/design-fields.ts +0 -264
  409. package/src/new-project/templates.ts +0 -61
  410. package/src/panels/tab-bar.ts +0 -548
  411. package/src/settings/settings-modal.ts +0 -203
  412. /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
  413. /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
  414. /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
  415. /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
  416. /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
  417. /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
  418. /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
  419. /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
package/src/platform.ts CHANGED
@@ -10,6 +10,12 @@
10
10
  * init.js) before studio.js loads.
11
11
  *
12
12
  * See spec/desktop.md §3 for the full StudioPlatform interface.
13
+ *
14
+ * **Every call is counted.** `getPlatform()` hands out a counting proxy, not the raw adapter, so
15
+ * "is Studio waiting on I/O?" is one number rather than thirty hand-instrumented methods
16
+ * (`probe.idle()` condition 4, spec §13.5). Wrapping at the READ point rather than at
17
+ * `registerPlatform` is deliberate: desktop pre-registers its adapter on `window.__jxPlatform`
18
+ * without ever calling the registrar, and this is the seam both paths share.
13
19
  */
14
20
 
15
21
  import type { StudioPlatform } from "./types";
@@ -21,12 +27,100 @@ export function registerPlatform(platform: StudioPlatform) {
21
27
  g.__jxPlatform = platform;
22
28
  }
23
29
 
30
+ // ─── In-flight accounting ─────────────────────────────────────────────────────
31
+
32
+ /** Method name → how many of its calls have not settled. Entries are deleted at zero. */
33
+ const inFlight = new Map<string, number>();
34
+
35
+ /**
36
+ * One entry per platform call whose promise has not settled, named by its method.
37
+ *
38
+ * Repeats are meaningful: two concurrent `gitStatus` reads are two reasons the shell is not
39
+ * settled, and the rejection message that names them is the whole point of §13.4 — 115 sleeps were
40
+ * 115 places that could not fail.
41
+ */
42
+ export function platformInFlight(): string[] {
43
+ const names: string[] = [];
44
+ for (const [method, count] of inFlight) {
45
+ for (let i = 0; i < count; i++) {
46
+ names.push(method);
47
+ }
48
+ }
49
+ return names;
50
+ }
51
+
52
+ function enter(method: string): void {
53
+ inFlight.set(method, (inFlight.get(method) ?? 0) + 1);
54
+ }
55
+
56
+ function leave(method: string): void {
57
+ const count = (inFlight.get(method) ?? 1) - 1;
58
+ if (count > 0) {
59
+ inFlight.set(method, count);
60
+ } else {
61
+ inFlight.delete(method);
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Wrap an adapter so every promise-returning member is counted while it is outstanding.
67
+ *
68
+ * Synchronous members are passed through untouched — they cannot be outstanding. Wrappers are
69
+ * memoised per property so `platform.readFile === platform.readFile`, which matters because call
70
+ * sites cache and compare these (`live-context.ts` tests `typeof platform[key] === "function"` to
71
+ * derive `capability.*`, and a fresh closure per read would allocate on every predicate).
72
+ */
73
+ function countingPlatform(platform: StudioPlatform): StudioPlatform {
74
+ const wrappers = new Map<PropertyKey, { raw: unknown; wrapper: unknown }>();
75
+ return new Proxy(platform, {
76
+ get(target, property) {
77
+ // `this` stays the raw adapter: a proxy receiver would re-enter this trap for every internal
78
+ // Property read the method makes, counting nothing and costing everything.
79
+ const value = Reflect.get(target, property) as unknown;
80
+ if (typeof value !== "function" || typeof property !== "string") {
81
+ return value;
82
+ }
83
+ // Keyed by the FUNCTION, not just the name: an adapter whose method is replaced later (a
84
+ // Lazily-installed capability, a test swapping one out) must not keep answering through a
85
+ // Wrapper closed over the old implementation.
86
+ const cached = wrappers.get(property);
87
+ if (cached && cached.raw === value) {
88
+ return cached.wrapper;
89
+ }
90
+ const method = property;
91
+ const wrapper = (...args: unknown[]): unknown => {
92
+ const result = (value as (...a: unknown[]) => unknown).apply(target, args);
93
+ if (typeof (result as PromiseLike<unknown> | null)?.then !== "function") {
94
+ return result;
95
+ }
96
+ enter(method);
97
+ const settle = () => {
98
+ leave(method);
99
+ };
100
+ // Both arms: a rejected platform call is a call that FINISHED. Leaving it counted would
101
+ // Wedge every later `idle()` behind an error the caller already handled.
102
+ (result as PromiseLike<unknown>).then(settle, settle);
103
+ return result;
104
+ };
105
+ wrappers.set(property, { raw: value, wrapper });
106
+ return wrapper;
107
+ },
108
+ });
109
+ }
110
+
111
+ /** The adapter the counting proxy currently wraps, so re-registration re-wraps and nothing else. */
112
+ let counted: { raw: StudioPlatform; wrapped: StudioPlatform } | null = null;
113
+
24
114
  /** @returns {StudioPlatform} */
25
115
  export function getPlatform() {
26
- if (!g.__jxPlatform) {
116
+ const raw = g.__jxPlatform;
117
+ if (!raw) {
27
118
  throw new Error("No platform registered. Call registerPlatform() before starting Studio.");
28
119
  }
29
- return g.__jxPlatform;
120
+ if (counted?.raw !== raw) {
121
+ counted = { raw, wrapped: countingPlatform(raw) };
122
+ }
123
+ return counted.wrapped;
30
124
  }
31
125
 
32
126
  /** @returns {boolean} */
@@ -11,6 +11,8 @@
11
11
  * gitClone, resolveClass, component discovery, code services.
12
12
  */
13
13
 
14
+ import { negotiateCollab } from "@jxsuite/collab/negotiate";
15
+ import type { CollabNegotiation } from "@jxsuite/collab/negotiate";
14
16
  import type { WsCollabConnection } from "@jxsuite/collab/client";
15
17
  import type { ProjectConfig } from "@jxsuite/schema/types";
16
18
  import type {
@@ -25,11 +27,13 @@ import type {
25
27
  PackageInfo,
26
28
  ProjectListEntry,
27
29
  ProjectSchemasResponse,
30
+ ReferencesResult,
28
31
  RenameResult,
29
32
  RepoInfo,
30
33
  StarterInfo,
31
34
  StudioPlatform,
32
35
  } from "../types";
36
+ import { problemDetail, problemSlug } from "@jxsuite/protocol";
33
37
 
34
38
  export interface CloudProject {
35
39
  owner: string;
@@ -52,7 +56,13 @@ interface SessionEventWire {
52
56
  sha?: string;
53
57
  }
54
58
 
55
- /** Message-level failure body every platform route uses. */
59
+ /**
60
+ * Message-level failure body every platform route uses.
61
+ *
62
+ * `error` is the pre-RFC-9457 name and is read through `problemDetail`, which also reads a problem
63
+ * document's `detail` — so this one reader covers a backend that has migrated and one that has
64
+ * not.
65
+ */
56
66
  interface ErrorBody {
57
67
  error?: string;
58
68
  code?: string;
@@ -60,8 +70,7 @@ interface ErrorBody {
60
70
 
61
71
  async function errorMessage(res: Response, fallback: string): Promise<string> {
62
72
  try {
63
- const body = (await res.json()) as ErrorBody;
64
- return body.error ?? fallback;
73
+ return problemDetail(await res.json()) ?? fallback;
65
74
  } catch {
66
75
  return fallback;
67
76
  }
@@ -164,6 +173,8 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
164
173
  * promise so concurrent first opens share the connection instead of racing two sockets.
165
174
  */
166
175
  let collabConnection: Promise<WsCollabConnection> | null = null;
176
+ /** Lazy subprotocol negotiation from the gateway's capability probe (null = not asked yet). */
177
+ let collabNegotiation: Promise<CollabNegotiation> | null = null;
167
178
 
168
179
  function api(path: string, init?: RequestInit): Promise<Response> {
169
180
  if (!project) {
@@ -309,6 +320,25 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
309
320
  );
310
321
  },
311
322
 
323
+ /**
324
+ * Usage counts, computed SERVER-SIDE. The walker lives in `@jxsuite/server`, which the cloud
325
+ * target already runs against the ProjectSession's working tree, so cloud is not a host that
326
+ * degrades to "unknown" — it answers the same query the desktop does, over the same engine.
327
+ */
328
+ async findReferences(target: { path?: string; tagName?: string }): Promise<ReferencesResult> {
329
+ const params = new URLSearchParams();
330
+ if (target.path) {
331
+ params.set("path", target.path);
332
+ }
333
+ if (target.tagName) {
334
+ params.set("tag", target.tagName);
335
+ }
336
+ return okJson<ReferencesResult>(
337
+ await api(`/references?${params.toString()}`),
338
+ `Failed to find references: ${target.path ?? target.tagName ?? ""}`,
339
+ );
340
+ },
341
+
312
342
  async createDirectory(_path: string) {
313
343
  // Directories exist implicitly in the virtual tree (created on write).
314
344
  },
@@ -318,11 +348,29 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
318
348
  * path, per the shared ProjectSession working tree). Backends without the endpoint (or with the
319
349
  * flag off) refuse the upgrade and Studio degrades to solo editing. The wire client's
320
350
  * evaluation defers behind the dynamic import until a doc opens.
351
+ *
352
+ * A plain GET on the same URL is the subprotocol negotiation, and this adapter did not make one
353
+ * before. **A probe that does not answer is not a refusal here.** The gateway is deployed
354
+ * separately from this bundle, so a 404 or a network error means "older gateway", and treating
355
+ * that as no-collab would take working co-editing away from every session pointed at one. It
356
+ * connects as it always has, offering nothing — which is also the only handshake-safe answer to
357
+ * a server that would echo nothing (RFC 6455 §4.1).
321
358
  */
322
359
  async collab(docPath: string) {
323
360
  if (!project || typeof WebSocket === "undefined" || typeof location === "undefined") {
324
361
  return null;
325
362
  }
363
+ collabNegotiation ??= api("/collab")
364
+ .then(async (res) =>
365
+ res.ok ? negotiateCollab(await res.json()) : { offer: [], refused: null },
366
+ )
367
+ .catch(() => ({ offer: [], refused: null }));
368
+ const negotiated = await collabNegotiation;
369
+ if (negotiated.refused !== null) {
370
+ console.warn(`Collaboration unavailable: ${negotiated.refused}`);
371
+ return null;
372
+ }
373
+ const { offer } = negotiated;
326
374
  collabConnection ??= (async () => {
327
375
  const { createWsCollabConnection } = await import("@jxsuite/collab/client");
328
376
  const scheme = location.protocol === "https:" ? "wss" : "ws";
@@ -331,6 +379,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
331
379
  // The DO has no GitHub token on a WS message; a plain read hydrates + caches the row.
332
380
  await api(`/file?path=${encodeURIComponent(path)}`);
333
381
  },
382
+ protocols: offer,
334
383
  url: `${scheme}://${location.host}${base}/collab`,
335
384
  });
336
385
  })();
@@ -681,6 +730,9 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
681
730
  if (target && typeof window !== "undefined") {
682
731
  window.open(editUrl(target), "_blank", "noopener");
683
732
  }
733
+ // `_blank` always makes a tab; a browser tab already showing this project is not something
734
+ // The page can see, let alone raise.
735
+ return { focused: false };
684
736
  },
685
737
 
686
738
  /**
@@ -720,10 +772,17 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
720
772
  // Preserve the structured 403 (needs_installation_access + installUrl) so the New
721
773
  // Project modal can render an install link instead of flattened text.
722
774
  const body = (await res.json().catch(() => null)) as
723
- | (ErrorBody & { installUrl?: string })
775
+ | (ErrorBody & { installUrl?: string; type?: string })
724
776
  | null;
725
- throw Object.assign(new Error(body?.error ?? "Failed to create project"), {
726
- ...(body?.code ? { code: body.code } : {}),
777
+ /*
778
+ * `code` survives as the machine-readable discriminator the modal branches on, and a
779
+ * problem document supplies it from its `type` — `problemSlug` derives the same string the
780
+ * old `code` field carried, so the modal's branch is unchanged either way.
781
+ */
782
+ throw Object.assign(new Error(problemDetail(body) ?? "Failed to create project"), {
783
+ ...((problemSlug(body?.type) ?? body?.code)
784
+ ? { code: problemSlug(body?.type) ?? body?.code }
785
+ : {}),
727
786
  ...(body?.installUrl ? { installUrl: body.installUrl } : {}),
728
787
  });
729
788
  }
@@ -900,9 +959,13 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
900
959
  settle(await fetchCfConnection());
901
960
  return;
902
961
  }
903
- timer = window.setTimeout(() => void poll(), 1500);
962
+ timer = window.setTimeout(() => {
963
+ void poll();
964
+ }, 1500);
904
965
  };
905
- timer = window.setTimeout(() => void poll(), 1500);
966
+ timer = window.setTimeout(() => {
967
+ void poll();
968
+ }, 1500);
906
969
  });
907
970
  },
908
971
 
@@ -10,6 +10,8 @@
10
10
 
11
11
  import { streamImport } from "../services/import-client";
12
12
  import { canPickDirectory, pickDirectoryPath } from "../services/directory-picker";
13
+ import { negotiateCollab } from "@jxsuite/collab/negotiate";
14
+ import type { CollabNegotiation } from "@jxsuite/collab/negotiate";
13
15
  import type { WsCollabConnection } from "@jxsuite/collab/client";
14
16
  import type { ProjectConfig } from "@jxsuite/schema/types";
15
17
  import type {
@@ -28,11 +30,14 @@ import type {
28
30
  ImportProgressEvent,
29
31
  ImportSiteOptions,
30
32
  ProjectSchemasResponse,
33
+ ReferencesResult,
31
34
  RenameResult,
32
35
  SecretsSetRequest,
33
36
  SecretsSetResponse,
37
+ SiteBuildResult,
34
38
  StarterInfo,
35
39
  } from "../types";
40
+ import { problemDetail, problemMessage } from "@jxsuite/protocol";
36
41
 
37
42
  /** A directory entry from the server, tolerating extra wire fields. */
38
43
  type WireDirEntry = DirEntry & Record<string, unknown>;
@@ -61,8 +66,12 @@ interface SiteEntry {
61
66
  */
62
67
  export function createDevServerPlatform() {
63
68
  let _projectRoot = "";
64
- /** Lazy /__studio/collab capability probe (null = not asked yet). */
65
- let _collabProbe: Promise<boolean> | null = null;
69
+ /**
70
+ * Lazy /__studio/collab capability probe (null = not asked yet). Its result is the subprotocol
71
+ * negotiation, not a boolean: the probe is the only place the client can learn what envelope the
72
+ * server speaks without risking the handshake (see `@jxsuite/collab/negotiate`).
73
+ */
74
+ let _collabProbe: Promise<CollabNegotiation | null> | null = null;
66
75
  /**
67
76
  * One multiplexed collab socket per page; per-doc handles come from openDoc. Memoized as a
68
77
  * promise so concurrent first opens share the connection instead of racing two sockets.
@@ -142,7 +151,7 @@ export function createDevServerPlatform() {
142
151
  if (!res.ok) {
143
152
  const body = (await readJson<ErrorBody>(res).catch(() => ({}))) as ErrorBody;
144
153
  throw new Error(
145
- `Could not open ${r}: ${body.error || `activation failed (${res.status})`}`,
154
+ `Could not open ${r}: ${problemDetail(body) ?? `activation failed (${res.status})`}`,
146
155
  );
147
156
  }
148
157
  },
@@ -281,7 +290,7 @@ export function createDevServerPlatform() {
281
290
  });
282
291
  if (!res.ok) {
283
292
  const data = await readJson<ErrorBody>(res);
284
- throw new Error(data.error || "Failed to create project");
293
+ throw new Error(problemDetail(data) ?? "Failed to create project");
285
294
  }
286
295
  return await res.json();
287
296
  },
@@ -425,6 +434,39 @@ export function createDevServerPlatform() {
425
434
  return report;
426
435
  },
427
436
 
437
+ /**
438
+ * Where a file / component tag is used, over the same walker the rename above writes through.
439
+ * The engine caches the sweep server-side and drops it from the dev server's own file watcher,
440
+ * so the three renderings never disagree and never re-scan the project per keystroke.
441
+ *
442
+ * @param {{ path?: string; tagName?: string }} target
443
+ */
444
+ async findReferences(target: { path?: string; tagName?: string }): Promise<ReferencesResult> {
445
+ const params = new URLSearchParams();
446
+ if (target.path) {
447
+ params.set("path", serverPath(target.path));
448
+ }
449
+ if (target.tagName) {
450
+ params.set("tag", target.tagName);
451
+ }
452
+ const res = await fetch(`/__studio/references?${params.toString()}`);
453
+ if (!res.ok) {
454
+ throw new Error(`Failed to find references: ${target.path ?? target.tagName ?? ""}`);
455
+ }
456
+ const result = await readJson<ReferencesResult>(res);
457
+ // Server-root-relative report paths → project-relative, as renameFile already does.
458
+ if (typeof result.path === "string") {
459
+ result.path = stripRoot(result.path);
460
+ }
461
+ for (const f of result.files ?? []) {
462
+ f.path = stripRoot(f.path);
463
+ }
464
+ for (const e of result.errors ?? []) {
465
+ e.path = stripRoot(e.path);
466
+ }
467
+ return result;
468
+ },
469
+
428
470
  /**
429
471
  * Subscribe to filesystem change events over the dev server's SSE stream. Listens for the named
430
472
  * "fs" event (the preview iframe's default `onmessage` ignores it), strips paths to
@@ -467,6 +509,12 @@ export function createDevServerPlatform() {
467
509
  * server-root-relative path). Probes capability once — older servers without the endpoint
468
510
  * degrade to solo editing; the wire client's evaluation defers behind the dynamic import until
469
511
  * a doc opens.
512
+ *
513
+ * The same probe carries the subprotocol negotiation. A server that advertises no `protocols`
514
+ * predates it and gets no offer, because an offer it cannot echo would fail the handshake
515
+ * outright (RFC 6455 §4.1); a server that advertises an envelope this build does not speak is
516
+ * refused here, where the reason can be said, rather than in a room where the two would merge
517
+ * divergent histories.
470
518
  */
471
519
  async collab(docPath: string) {
472
520
  if (typeof WebSocket === "undefined" || typeof location === "undefined") {
@@ -474,16 +522,23 @@ export function createDevServerPlatform() {
474
522
  }
475
523
  if (_collabProbe === null) {
476
524
  _collabProbe = fetch("/__studio/collab")
477
- .then((res) => res.ok)
478
- .catch(() => false);
525
+ .then(async (res) => (res.ok ? negotiateCollab(await res.json()) : null))
526
+ .catch(() => null);
479
527
  }
480
- if (!(await _collabProbe)) {
528
+ const negotiation = await _collabProbe;
529
+ if (negotiation === null) {
481
530
  return null;
482
531
  }
532
+ if (negotiation.refused !== null) {
533
+ console.warn(`Collaboration unavailable: ${negotiation.refused}`);
534
+ return null;
535
+ }
536
+ const { offer } = negotiation;
483
537
  _collabConnection ??= (async () => {
484
538
  const { createWsCollabConnection } = await import("@jxsuite/collab/client");
485
539
  const scheme = location.protocol === "https:" ? "wss" : "ws";
486
540
  return createWsCollabConnection({
541
+ protocols: offer,
487
542
  url: `${scheme}://${location.host}/__studio/collab`,
488
543
  });
489
544
  })();
@@ -707,7 +762,7 @@ export function createDevServerPlatform() {
707
762
  );
708
763
  if (!res.ok) {
709
764
  const data = await readJson<ErrorBody>(res);
710
- throw new Error(data.error || "Failed to list connections");
765
+ throw new Error(problemDetail(data) ?? "Failed to list connections");
711
766
  }
712
767
  return await readJson<DataConnectionsResponse>(res);
713
768
  },
@@ -724,7 +779,7 @@ export function createDevServerPlatform() {
724
779
  );
725
780
  const data = await readJson<DataConnectionTestResult & ErrorBody>(res);
726
781
  if (!res.ok) {
727
- throw new Error(data.error || "Connection test failed");
782
+ throw new Error(problemDetail(data) ?? "Connection test failed");
728
783
  }
729
784
  return data;
730
785
  },
@@ -738,7 +793,7 @@ export function createDevServerPlatform() {
738
793
  });
739
794
  const data = await readJson<DataPushResult & ErrorBody>(res);
740
795
  if (!res.ok) {
741
- throw new Error(data.error || "Schema push failed");
796
+ throw new Error(problemDetail(data) ?? "Schema push failed");
742
797
  }
743
798
  return data;
744
799
  },
@@ -764,7 +819,7 @@ export function createDevServerPlatform() {
764
819
  const res = await fetch(`/__studio/data/rows?${params}`);
765
820
  const data = await readJson<DataRowsResult & ErrorBody>(res);
766
821
  if (!res.ok) {
767
- throw new Error(data.error || "Failed to load rows");
822
+ throw new Error(problemDetail(data) ?? "Failed to load rows");
768
823
  }
769
824
  return data;
770
825
  },
@@ -777,7 +832,7 @@ export function createDevServerPlatform() {
777
832
  });
778
833
  const data = await readJson<{ row: Record<string, unknown> } & ErrorBody>(res);
779
834
  if (!res.ok) {
780
- throw new Error(data.error || "Insert failed");
835
+ throw new Error(problemDetail(data) ?? "Insert failed");
781
836
  }
782
837
  return data;
783
838
  },
@@ -790,7 +845,7 @@ export function createDevServerPlatform() {
790
845
  });
791
846
  const data = await readJson<{ row: Record<string, unknown> } & ErrorBody>(res);
792
847
  if (!res.ok) {
793
- throw new Error(data.error || "Update failed");
848
+ throw new Error(problemDetail(data) ?? "Update failed");
794
849
  }
795
850
  return data;
796
851
  },
@@ -807,7 +862,7 @@ export function createDevServerPlatform() {
807
862
  const res = await fetch(`/__studio/data/rows?${params}`, { method: "DELETE" });
808
863
  const data = await readJson<{ ok: boolean } & ErrorBody>(res);
809
864
  if (!res.ok) {
810
- throw new Error(data.error || "Delete failed");
865
+ throw new Error(problemDetail(data) ?? "Delete failed");
811
866
  }
812
867
  return data;
813
868
  },
@@ -817,7 +872,7 @@ export function createDevServerPlatform() {
817
872
  const res = await fetch(`/__studio/secrets?dir=${encodeURIComponent(serverPath("."))}`);
818
873
  if (!res.ok) {
819
874
  const data = await readJson<ErrorBody>(res);
820
- throw new Error(data.error || "Failed to list secrets");
875
+ throw new Error(problemDetail(data) ?? "Failed to list secrets");
821
876
  }
822
877
  const data = await readJson<{ names: string[] }>(res);
823
878
  return data.names;
@@ -832,7 +887,7 @@ export function createDevServerPlatform() {
832
887
  });
833
888
  const data = await readJson<SecretsSetResponse & ErrorBody>(res);
834
889
  if (!res.ok) {
835
- throw new Error(data.error || "Failed to write secrets");
890
+ throw new Error(problemDetail(data) ?? "Failed to write secrets");
836
891
  }
837
892
  return data;
838
893
  },
@@ -850,7 +905,7 @@ export function createDevServerPlatform() {
850
905
  });
851
906
  const data = await readJson<{ error?: string; result?: unknown }>(res);
852
907
  if (!res.ok) {
853
- throw new Error(data.error || "Format action failed");
908
+ throw new Error(problemDetail(data) ?? "Format action failed");
854
909
  }
855
910
  return data.result;
856
911
  },
@@ -930,7 +985,7 @@ export function createDevServerPlatform() {
930
985
  });
931
986
  if (!res.ok) {
932
987
  const body = await readJson<ErrorBody>(res);
933
- throw new Error(body.error);
988
+ throw new Error(problemMessage(body));
934
989
  }
935
990
  return await res.json();
936
991
  },
@@ -944,7 +999,7 @@ export function createDevServerPlatform() {
944
999
  });
945
1000
  if (!res.ok) {
946
1001
  const body = await readJson<ErrorBody>(res);
947
- throw new Error(body.error);
1002
+ throw new Error(problemMessage(body));
948
1003
  }
949
1004
  return await res.json();
950
1005
  },
@@ -958,7 +1013,7 @@ export function createDevServerPlatform() {
958
1013
  });
959
1014
  if (!res.ok) {
960
1015
  const body = await readJson<ErrorBody>(res);
961
- throw new Error(body.error);
1016
+ throw new Error(problemMessage(body));
962
1017
  }
963
1018
  return await res.json();
964
1019
  },
@@ -972,7 +1027,7 @@ export function createDevServerPlatform() {
972
1027
  });
973
1028
  if (!res.ok) {
974
1029
  const body = await readJson<ErrorBody>(res);
975
- throw new Error(body.error);
1030
+ throw new Error(problemMessage(body));
976
1031
  }
977
1032
  return await res.json();
978
1033
  },
@@ -981,7 +1036,7 @@ export function createDevServerPlatform() {
981
1036
  const res = await fetch("/__studio/git/pull", { method: "POST" });
982
1037
  if (!res.ok) {
983
1038
  const body = await readJson<ErrorBody>(res);
984
- throw new Error(body.error);
1039
+ throw new Error(problemMessage(body));
985
1040
  }
986
1041
  return await res.json();
987
1042
  },
@@ -990,7 +1045,7 @@ export function createDevServerPlatform() {
990
1045
  const res = await fetch("/__studio/git/fetch", { method: "POST" });
991
1046
  if (!res.ok) {
992
1047
  const body = await readJson<ErrorBody>(res);
993
- throw new Error(body.error);
1048
+ throw new Error(problemMessage(body));
994
1049
  }
995
1050
  return await res.json();
996
1051
  },
@@ -1004,7 +1059,7 @@ export function createDevServerPlatform() {
1004
1059
  });
1005
1060
  if (!res.ok) {
1006
1061
  const body = await readJson<ErrorBody>(res);
1007
- throw new Error(body.error);
1062
+ throw new Error(problemMessage(body));
1008
1063
  }
1009
1064
  return await res.json();
1010
1065
  },
@@ -1018,7 +1073,7 @@ export function createDevServerPlatform() {
1018
1073
  });
1019
1074
  if (!res.ok) {
1020
1075
  const body = await readJson<ErrorBody>(res);
1021
- throw new Error(body.error);
1076
+ throw new Error(problemMessage(body));
1022
1077
  }
1023
1078
  return await res.json();
1024
1079
  },
@@ -1055,7 +1110,7 @@ export function createDevServerPlatform() {
1055
1110
  });
1056
1111
  if (!res.ok) {
1057
1112
  const body = await readJson<ErrorBody>(res);
1058
- throw new Error(body.error);
1113
+ throw new Error(problemMessage(body));
1059
1114
  }
1060
1115
  return await res.json();
1061
1116
  },
@@ -1069,7 +1124,7 @@ export function createDevServerPlatform() {
1069
1124
  });
1070
1125
  if (!res.ok) {
1071
1126
  const body = await readJson<ErrorBody>(res);
1072
- throw new Error(body.error);
1127
+ throw new Error(problemMessage(body));
1073
1128
  }
1074
1129
  return await res.json();
1075
1130
  },
@@ -1078,8 +1133,16 @@ export function createDevServerPlatform() {
1078
1133
  const res = await fetch("/__studio/git/init", { method: "POST" });
1079
1134
  if (!res.ok) {
1080
1135
  const body = await readJson<ErrorBody>(res);
1081
- throw new Error(body.error);
1136
+ throw new Error(problemMessage(body));
1137
+ }
1138
+ },
1139
+ async buildSite() {
1140
+ const res = await fetch("/__studio/build", { method: "POST" });
1141
+ if (!res.ok) {
1142
+ const body = await readJson<ErrorBody>(res);
1143
+ throw new Error(problemDetail(body) ?? "The site could not be built.");
1082
1144
  }
1145
+ return (await res.json()) as SiteBuildResult;
1083
1146
  },
1084
1147
 
1085
1148
  /**
@@ -1094,7 +1157,7 @@ export function createDevServerPlatform() {
1094
1157
  });
1095
1158
  if (!res.ok) {
1096
1159
  const body = await readJson<ErrorBody>(res);
1097
- throw new Error(body.error);
1160
+ throw new Error(problemMessage(body));
1098
1161
  }
1099
1162
  },
1100
1163