@jxsuite/studio 6.1.1 → 6.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/dist/chunks/{2020-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
  2. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  3. package/dist/chunks/adapter-4912g339.js +4 -0
  4. package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
  5. package/dist/chunks/cf-settings-br6105tr.js +4 -0
  6. package/dist/chunks/color-28ksk2qm.js +4 -0
  7. package/dist/chunks/color-area-0fj8a4ga.js +4 -0
  8. package/dist/chunks/color-field-xch8kx2g.js +4 -0
  9. package/dist/chunks/color-slider-jxd8v350.js +4 -0
  10. package/dist/chunks/combobox-p0efwjke.js +4 -0
  11. package/dist/chunks/components-db68vsn7.js +4 -0
  12. package/dist/chunks/content-source-1449qesq.js +4 -0
  13. package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
  14. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  15. package/dist/chunks/editor-x9jn86a7.js +4 -0
  16. package/dist/chunks/entry-commands-may24cpt.js +4 -0
  17. package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
  18. package/dist/chunks/file-ops-x9v54pcj.js +4 -0
  19. package/dist/chunks/files-j3knqf0s.js +4 -0
  20. package/dist/chunks/format-host-tyre2trb.js +4 -0
  21. package/dist/chunks/fs-events-64ma9htc.js +4 -0
  22. package/dist/chunks/git-panel-84ps5dex.js +4 -0
  23. package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
  24. package/dist/chunks/icons-pnfz478q.js +4 -0
  25. package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
  26. package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
  27. package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
  28. package/dist/chunks/iframe-entry-zap785cw.js +5 -0
  29. package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
  30. package/dist/chunks/index-b8xw3vy9.js +4 -0
  31. package/dist/chunks/{index-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
  32. package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
  33. package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
  34. package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
  35. package/dist/chunks/layers-h4xp1pss.js +4 -0
  36. package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
  37. package/dist/chunks/listbox-e74qjyq6.js +4 -0
  38. package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
  39. package/dist/chunks/media-picker-2cweexc5.js +4 -0
  40. package/dist/chunks/menu-n6yzswmy.js +4 -0
  41. package/dist/chunks/menu-ynw13y0s.js +4 -0
  42. package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
  43. package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
  44. package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
  45. package/dist/chunks/notify-cj5zbrs2.js +4 -0
  46. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  47. package/dist/chunks/parse-b7ddhr8m.js +4 -0
  48. package/dist/chunks/platform-3dfws9js.js +4 -0
  49. package/dist/chunks/popover-jt2gxmzs.js +4 -0
  50. package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
  51. package/dist/chunks/quick-search-0dajrwqg.js +4 -0
  52. package/dist/chunks/references-49qgt404.js +4 -0
  53. package/dist/chunks/right-panel-jm1bwe53.js +4 -0
  54. package/dist/chunks/section-registry-6kwc4fky.js +4 -0
  55. package/dist/chunks/select-rzds841e.js +4 -0
  56. package/dist/chunks/split-n2gfpm5m.js +4 -0
  57. package/dist/chunks/{studio-1q1sh2ax.js → studio-0q988f9w.js} +3 -3
  58. package/dist/chunks/studio-0rt52vpq.js +5 -0
  59. package/dist/chunks/studio-18vgbhs5.js +5 -0
  60. package/dist/chunks/{studio-h46vtzk8.js → studio-1fxkaaea.js} +4 -4
  61. package/dist/chunks/studio-24mccdrj.js +5 -0
  62. package/dist/chunks/studio-2eh507zk.js +9 -0
  63. package/dist/chunks/studio-2hcbccfv.js +5 -0
  64. package/dist/chunks/studio-2j1cb95x.js +5 -0
  65. package/dist/chunks/studio-2jbs3rxv.js +5 -0
  66. package/dist/chunks/{studio-rv11kfwa.js → studio-485046te.js} +7 -7
  67. package/dist/chunks/studio-4h8k4dw9.js +5 -0
  68. package/dist/chunks/studio-5f6n18kx.js +5 -0
  69. package/dist/chunks/studio-5gthpky6.js +5 -0
  70. package/dist/chunks/studio-5ve6bbep.js +5 -0
  71. package/dist/chunks/studio-6ep3js6b.js +9 -0
  72. package/dist/chunks/studio-6wkmf3wz.js +9 -0
  73. package/dist/chunks/studio-841rf3cg.js +5 -0
  74. package/dist/chunks/studio-8gmwgheg.js +5 -0
  75. package/dist/chunks/studio-8qm0ep50.js +5 -0
  76. package/dist/chunks/{studio-8grwxtqk.js → studio-90pq9km1.js} +4 -4
  77. package/dist/chunks/studio-924p1tm1.js +6 -0
  78. package/dist/chunks/{studio-pre0skq6.js → studio-a3g98wjr.js} +4 -4
  79. package/dist/chunks/studio-a3shpz9y.js +5 -0
  80. package/dist/chunks/studio-amsbaaar.js +6 -0
  81. package/dist/chunks/studio-at5spjbc.js +7 -0
  82. package/dist/chunks/studio-b2xv945e.js +5 -0
  83. package/dist/chunks/studio-bn5nkafw.js +5 -0
  84. package/dist/chunks/studio-bw6q5xjf.js +9 -0
  85. package/dist/chunks/studio-c7q0t9x1.js +5 -0
  86. package/dist/chunks/studio-camnhc96.js +6 -0
  87. package/dist/chunks/studio-cffqvnzd.js +5 -0
  88. package/dist/chunks/studio-d81xfh1g.js +5 -0
  89. package/dist/chunks/studio-dgz8d0c1.js +5 -0
  90. package/dist/chunks/studio-efvfrsf8.js +5 -0
  91. package/dist/chunks/studio-er30bpcx.js +5 -0
  92. package/dist/chunks/studio-ezscgr64.js +5 -0
  93. package/dist/chunks/studio-ffrrncvz.js +5 -0
  94. package/dist/chunks/studio-fpphgn8y.js +10 -0
  95. package/dist/chunks/studio-j1kvhdjk.js +4 -0
  96. package/dist/chunks/{studio-vrmcjf9g.js → studio-j430n16g.js} +5 -5
  97. package/dist/chunks/studio-jjkg84nj.js +5 -0
  98. package/dist/chunks/studio-m0q32ars.js +4 -0
  99. package/dist/chunks/studio-m6bdst11.js +5 -0
  100. package/dist/chunks/studio-nv2cptd4.js +64 -0
  101. package/dist/chunks/studio-nwfrc98n.js +5 -0
  102. package/dist/chunks/studio-p1wgvp7r.js +5 -0
  103. package/dist/chunks/studio-pag2wncm.js +5 -0
  104. package/dist/chunks/studio-qvanvzfd.js +5 -0
  105. package/dist/chunks/studio-qwa64kt7.js +5 -0
  106. package/dist/chunks/studio-rk1zc4x3.js +928 -0
  107. package/dist/chunks/studio-se2r3ptc.js +5 -0
  108. package/dist/chunks/studio-sg2a0dh0.js +5 -0
  109. package/dist/chunks/studio-tjzjhe68.js +5 -0
  110. package/dist/chunks/{studio-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
  111. package/dist/chunks/{studio-kggey1jt.js → studio-v0jzqdjm.js} +4 -4
  112. package/dist/chunks/studio-v2w7q8r1.js +7 -0
  113. package/dist/chunks/studio-v5vjq1h0.js +4 -0
  114. package/dist/chunks/studio-v8aga3vp.js +14 -0
  115. package/dist/chunks/studio-vfcdrfmv.js +5 -0
  116. package/dist/chunks/studio-vmfkgdjf.js +5 -0
  117. package/dist/chunks/studio-wt1816jj.js +5 -0
  118. package/dist/chunks/studio-wz73q5kq.js +4 -0
  119. package/dist/chunks/studio-y04qtxvp.js +7 -0
  120. package/dist/chunks/studio-y21g8zzg.js +5 -0
  121. package/dist/chunks/{studio-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
  122. package/dist/chunks/studio-ynn90f58.js +16 -0
  123. package/dist/chunks/studio-yxz682sx.js +5 -0
  124. package/dist/chunks/studio-zp7snvkq.js +5 -0
  125. package/dist/chunks/studio-zq4z6tm6.js +5 -0
  126. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  127. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  128. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  129. package/dist/chunks/toast-c9fn075p.js +4 -0
  130. package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
  131. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  132. package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
  133. package/dist/chunks/tree-mdq3v5cw.js +4 -0
  134. package/dist/chunks/{tsMode-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
  135. package/dist/chunks/workspace-jtfahpee.js +4 -0
  136. package/dist/chunks/ws-client-nze0k6mv.js +4 -0
  137. package/dist/iframe-entry.js +16 -16
  138. package/dist/manifest.json +63 -63
  139. package/dist/studio.js +97 -97
  140. package/package.json +6 -6
  141. package/src/about/about-modal.ts +4 -3
  142. package/src/account/action-flow.ts +45 -38
  143. package/src/account-status.ts +7 -2
  144. package/src/browse/library-layouts.ts +8 -5
  145. package/src/browse/library-model.ts +18 -6
  146. package/src/browse/library-pane.ts +37 -21
  147. package/src/browse/library-preview.ts +14 -9
  148. package/src/browse/library-source.ts +1 -1
  149. package/src/canvas/asset-refs.ts +24 -9
  150. package/src/canvas/asset-resolve.ts +19 -23
  151. package/src/canvas/canvas-helpers.ts +7 -6
  152. package/src/canvas/canvas-live-render.ts +44 -53
  153. package/src/canvas/canvas-patcher.ts +30 -30
  154. package/src/canvas/canvas-perf.ts +11 -5
  155. package/src/canvas/canvas-render.ts +62 -41
  156. package/src/canvas/canvas-surface.ts +5 -3
  157. package/src/canvas/canvas-utils.ts +90 -49
  158. package/src/canvas/dialog-path.ts +9 -4
  159. package/src/canvas/dialog-state.ts +1 -2
  160. package/src/canvas/diff-marks.ts +9 -16
  161. package/src/canvas/diff-toolbar.ts +8 -7
  162. package/src/canvas/edit-width-drag.ts +4 -1
  163. package/src/canvas/edit-width.ts +1 -3
  164. package/src/canvas/iframe-channel.ts +27 -13
  165. package/src/canvas/iframe-drop.ts +13 -12
  166. package/src/canvas/iframe-editable-root.ts +29 -16
  167. package/src/canvas/iframe-entry.ts +80 -63
  168. package/src/canvas/iframe-eval.ts +73 -49
  169. package/src/canvas/iframe-host.ts +135 -96
  170. package/src/canvas/iframe-inline-edit.ts +49 -30
  171. package/src/canvas/iframe-insert.ts +5 -4
  172. package/src/canvas/iframe-interaction.ts +30 -25
  173. package/src/canvas/iframe-overlay.ts +1 -1
  174. package/src/canvas/iframe-patch.ts +18 -15
  175. package/src/canvas/iframe-position.ts +12 -6
  176. package/src/canvas/iframe-protocol.ts +12 -16
  177. package/src/canvas/iframe-render.ts +36 -34
  178. package/src/canvas/iframe-slash.ts +24 -11
  179. package/src/canvas/iframe-subtree.ts +6 -2
  180. package/src/canvas/path-mapping.ts +19 -12
  181. package/src/canvas/popover-path.ts +7 -3
  182. package/src/canvas/popover-state.ts +1 -2
  183. package/src/canvas/serialize-scope.ts +13 -5
  184. package/src/canvas/stage-scrollbar.ts +2 -1
  185. package/src/canvas/surface-registry.ts +21 -3
  186. package/src/collab/collab-commands.ts +7 -2
  187. package/src/collab/collab-session.ts +84 -45
  188. package/src/collab/collab-state.ts +4 -3
  189. package/src/collab/monaco-binding.ts +16 -13
  190. package/src/collab/monaco-cursors.ts +5 -2
  191. package/src/commands/budget.ts +3 -3
  192. package/src/commands/command-args.ts +103 -71
  193. package/src/commands/context.ts +22 -20
  194. package/src/commands/keymap.ts +47 -43
  195. package/src/commands/levels.ts +3 -3
  196. package/src/commands/live-context.ts +7 -7
  197. package/src/commands/reference.ts +2 -1
  198. package/src/commands/registry.ts +12 -10
  199. package/src/commands/run-reported.ts +15 -10
  200. package/src/component-props.ts +46 -30
  201. package/src/content/collection-match.ts +5 -4
  202. package/src/content/draft-state.ts +4 -3
  203. package/src/content/entry-commands.ts +3 -2
  204. package/src/content/entry-editor.ts +29 -17
  205. package/src/content/entry-fields.ts +12 -7
  206. package/src/content/entry-model.ts +21 -12
  207. package/src/editor/canvas-context-menu.ts +1 -2
  208. package/src/editor/canvas-slash-bridge.ts +3 -6
  209. package/src/editor/content-slice.ts +16 -14
  210. package/src/editor/context-menu.ts +35 -22
  211. package/src/editor/convert-targets.ts +30 -35
  212. package/src/editor/convert-to-component.ts +11 -5
  213. package/src/editor/convert-to-repeater.ts +34 -22
  214. package/src/editor/editable-tags.ts +17 -2
  215. package/src/editor/file-drop-action.ts +21 -22
  216. package/src/editor/inline-edit-apply.ts +35 -17
  217. package/src/editor/inline-edit.ts +66 -50
  218. package/src/editor/inline-format.ts +59 -56
  219. package/src/editor/inline-link.ts +40 -15
  220. package/src/editor/insert-zone-action.ts +1 -1
  221. package/src/editor/merge-tags.ts +58 -19
  222. package/src/editor/repeater-scope.ts +39 -28
  223. package/src/editor/shortcuts.ts +32 -20
  224. package/src/editor/slash-menu.ts +1 -6
  225. package/src/files/asset-versions.ts +4 -4
  226. package/src/files/components.ts +15 -10
  227. package/src/files/elements.ts +5 -6
  228. package/src/files/file-ops.ts +77 -36
  229. package/src/files/files.ts +90 -95
  230. package/src/files/media-meta.ts +2 -1
  231. package/src/files/media-paths.ts +3 -0
  232. package/src/files/serialize-document.ts +2 -2
  233. package/src/format/constraints.ts +1 -1
  234. package/src/format/convert-file.ts +27 -13
  235. package/src/format/format-choices.ts +2 -1
  236. package/src/format/format-host.ts +76 -50
  237. package/src/github/github-auth-status.ts +27 -3
  238. package/src/github/github-auth.ts +19 -9
  239. package/src/github/github-publish.ts +24 -20
  240. package/src/grid/cell-editors.ts +46 -31
  241. package/src/grid/cell-popovers.ts +5 -3
  242. package/src/grid/edit-buffer.ts +10 -9
  243. package/src/grid/grid-controller.ts +20 -22
  244. package/src/grid/grid-layout.ts +21 -5
  245. package/src/grid/grid-open.ts +3 -6
  246. package/src/grid/grid-panel.ts +11 -4
  247. package/src/grid/grid-source.ts +8 -8
  248. package/src/grid/grid-view.ts +14 -17
  249. package/src/grid/redirects-grid.ts +14 -5
  250. package/src/grid/redirects.ts +16 -14
  251. package/src/grid/schema-columns.ts +25 -19
  252. package/src/grid/sources/connector-source.ts +47 -20
  253. package/src/grid/sources/content-source.ts +25 -24
  254. package/src/grid/sources/csv-file-source.ts +2 -2
  255. package/src/grid/tabulator-tables.d.ts +55 -34
  256. package/src/hosting/stage.ts +7 -7
  257. package/src/i18n/i18n-commands.ts +1 -2
  258. package/src/media/media-pane.ts +4 -1
  259. package/src/new-project/add-repo-modal.ts +20 -19
  260. package/src/new-project/import-tab.ts +10 -14
  261. package/src/new-project/location-fields.ts +2 -1
  262. package/src/new-project/new-project-modal.ts +12 -9
  263. package/src/packages/jxsuite-update.ts +4 -3
  264. package/src/packages/pull-package-sync.ts +26 -25
  265. package/src/page-params.ts +97 -68
  266. package/src/panels/activity-panel.ts +17 -9
  267. package/src/panels/ai-chat/attached-context.ts +13 -7
  268. package/src/panels/ai-chat/chat-view.ts +80 -73
  269. package/src/panels/ai-chat/composer.ts +30 -33
  270. package/src/panels/ai-chat/sessions-view.ts +1 -2
  271. package/src/panels/ai-panel.ts +23 -20
  272. package/src/panels/block-action-bar.ts +46 -35
  273. package/src/panels/bottom-dock.ts +5 -3
  274. package/src/panels/canvas-dnd-bridge.ts +31 -24
  275. package/src/panels/data-explorer.ts +62 -25
  276. package/src/panels/data-grid.ts +14 -11
  277. package/src/panels/dnd.ts +108 -118
  278. package/src/panels/editors.ts +52 -21
  279. package/src/panels/elements-panel.ts +10 -3
  280. package/src/panels/events-panel.ts +84 -69
  281. package/src/panels/formula-workspace.ts +76 -51
  282. package/src/panels/frontmatter-fields.ts +24 -19
  283. package/src/panels/frontmatter-panel.ts +44 -34
  284. package/src/panels/git-diff-open.ts +4 -4
  285. package/src/panels/git-panel.ts +49 -61
  286. package/src/panels/head-panel.ts +131 -111
  287. package/src/panels/i18n-panel.ts +10 -3
  288. package/src/panels/imports-panel.ts +23 -47
  289. package/src/panels/jump-bar.ts +48 -29
  290. package/src/panels/layers-panel.ts +97 -74
  291. package/src/panels/left-panel.ts +3 -3
  292. package/src/panels/pane-context.ts +31 -22
  293. package/src/panels/pane-grid.ts +49 -20
  294. package/src/panels/panel-registry.ts +22 -37
  295. package/src/panels/properties-panel.ts +175 -121
  296. package/src/panels/quick-search.ts +53 -31
  297. package/src/panels/right-panel.ts +3 -3
  298. package/src/panels/seo-modal.ts +13 -17
  299. package/src/panels/settings-menu.ts +15 -15
  300. package/src/panels/signals-panel.ts +153 -131
  301. package/src/panels/statement-editor.ts +230 -140
  302. package/src/panels/style-panel.ts +218 -205
  303. package/src/panels/style-utils.ts +114 -51
  304. package/src/panels/stylebook-doc.ts +57 -54
  305. package/src/panels/stylebook-layers-panel.ts +9 -9
  306. package/src/panels/stylebook-panel.ts +13 -17
  307. package/src/panels/tab-drop.ts +27 -11
  308. package/src/panels/tab-strip.ts +36 -26
  309. package/src/platform-errors.ts +57 -43
  310. package/src/platform.ts +58 -30
  311. package/src/platforms/cloud.ts +345 -175
  312. package/src/platforms/default-platform.ts +10 -4
  313. package/src/platforms/devserver.ts +129 -117
  314. package/src/platforms/read-batcher.ts +16 -8
  315. package/src/project-list.ts +2 -1
  316. package/src/publish/deploy-checklist.ts +8 -2
  317. package/src/publish/pages-service.ts +28 -13
  318. package/src/publish/publish-commands.ts +5 -4
  319. package/src/publish/publish-panel.ts +10 -6
  320. package/src/recent-projects.ts +15 -8
  321. package/src/resize-edges.ts +26 -36
  322. package/src/services/a11y-report.ts +26 -19
  323. package/src/services/agent-seed.ts +23 -11
  324. package/src/services/ai-ask.ts +9 -12
  325. package/src/services/ai-command-tools.ts +68 -62
  326. package/src/services/ai-import-tools.ts +80 -67
  327. package/src/services/ai-models.ts +17 -13
  328. package/src/services/ai-project-tools.ts +68 -32
  329. package/src/services/ai-session-store.ts +19 -10
  330. package/src/services/ai-system-prompt.ts +46 -20
  331. package/src/services/ai-tools.ts +71 -27
  332. package/src/services/ai-write-report.ts +20 -12
  333. package/src/services/ai-writes.ts +4 -4
  334. package/src/services/automation.ts +58 -31
  335. package/src/services/cem-export.ts +149 -58
  336. package/src/services/clock.ts +6 -1
  337. package/src/services/code-services.ts +37 -31
  338. package/src/services/context-manager.ts +14 -10
  339. package/src/services/context-resolver.ts +20 -8
  340. package/src/services/data-service.ts +19 -15
  341. package/src/services/directory-picker.ts +18 -12
  342. package/src/services/document-assistant.ts +39 -19
  343. package/src/services/gated-registry.ts +10 -6
  344. package/src/services/harness/chat-reducer.ts +23 -1
  345. package/src/services/import-client.ts +91 -38
  346. package/src/services/import-seed.ts +8 -2
  347. package/src/services/jx-validate.ts +28 -31
  348. package/src/services/live-preview.ts +0 -0
  349. package/src/services/live-surfaces.ts +6 -3
  350. package/src/services/model-uri.ts +10 -2
  351. package/src/services/module-preloads.ts +12 -8
  352. package/src/services/monaco-buffer.ts +43 -24
  353. package/src/services/monaco-lazy.ts +7 -8
  354. package/src/services/monaco-setup.ts +23 -16
  355. package/src/services/notify.ts +44 -17
  356. package/src/services/popover-report.ts +25 -10
  357. package/src/services/preview-eval.ts +20 -8
  358. package/src/services/profile.ts +13 -6
  359. package/src/services/project-path.ts +13 -10
  360. package/src/services/references.ts +0 -0
  361. package/src/services/render-critic.ts +8 -7
  362. package/src/services/settings/kernel.ts +13 -4
  363. package/src/services/settings/write-queue.ts +9 -9
  364. package/src/services/token-lint.ts +12 -10
  365. package/src/services/tool-executor.ts +17 -5
  366. package/src/services/tool-outcomes.ts +44 -24
  367. package/src/services/trusted-types.ts +24 -7
  368. package/src/settings/contexts-section.ts +11 -8
  369. package/src/settings/contributed-section.ts +79 -60
  370. package/src/settings/css-vars-editor.ts +37 -16
  371. package/src/settings/defs-editor.ts +38 -35
  372. package/src/settings/extension-rows.ts +16 -8
  373. package/src/settings/extension-sections.ts +23 -13
  374. package/src/settings/extensions-section.ts +4 -1
  375. package/src/settings/general-settings.ts +11 -8
  376. package/src/settings/locales-section.ts +20 -12
  377. package/src/settings/preferences-dialog.ts +9 -6
  378. package/src/settings/preferences-keymap.ts +7 -5
  379. package/src/settings/preferences-sections.ts +11 -5
  380. package/src/settings/project-sections.ts +1 -1
  381. package/src/settings/schema-field-ui.ts +9 -0
  382. package/src/settings/settings-document.ts +5 -5
  383. package/src/shell/tree.ts +6 -5
  384. package/src/shell.ts +104 -81
  385. package/src/site-context.ts +37 -22
  386. package/src/state.ts +41 -49
  387. package/src/store.ts +54 -34
  388. package/src/studio.ts +25 -75
  389. package/src/style/live-preview.ts +1 -1
  390. package/src/style/project-styles.ts +6 -7
  391. package/src/style/token-ref.ts +5 -4
  392. package/src/surfaces/about.ts +18 -19
  393. package/src/surfaces/add-repo.ts +17 -19
  394. package/src/surfaces/ai-chat.ts +31 -36
  395. package/src/surfaces/ai-credentials-form.ts +6 -16
  396. package/src/surfaces/ai-managed-connect.ts +3 -4
  397. package/src/surfaces/ai-model-picker.ts +3 -5
  398. package/src/surfaces/block-action-bar.ts +22 -11
  399. package/src/surfaces/boot-failure.ts +4 -5
  400. package/src/surfaces/bottom-dock.ts +9 -18
  401. package/src/surfaces/canvas-stage.ts +12 -11
  402. package/src/surfaces/cf-account-picker.ts +17 -18
  403. package/src/surfaces/commandbar.ts +14 -9
  404. package/src/surfaces/convert-repeater.ts +17 -19
  405. package/src/surfaces/data-actions.ts +9 -7
  406. package/src/surfaces/dialog.ts +26 -28
  407. package/src/surfaces/diff-toolbar.ts +9 -7
  408. package/src/surfaces/doc-header.ts +10 -19
  409. package/src/surfaces/empty-state.ts +7 -10
  410. package/src/surfaces/entry-editor.ts +14 -11
  411. package/src/surfaces/expression-editor.ts +11 -25
  412. package/src/surfaces/files-panel.ts +27 -14
  413. package/src/surfaces/formula-palette.ts +4 -5
  414. package/src/surfaces/git-panel.ts +7 -15
  415. package/src/surfaces/github-auth.ts +16 -20
  416. package/src/surfaces/github-publish.ts +17 -22
  417. package/src/surfaces/grid-cell.ts +30 -31
  418. package/src/surfaces/grid-open.ts +10 -14
  419. package/src/surfaces/grid-panel.ts +13 -9
  420. package/src/surfaces/grid-replace.ts +13 -13
  421. package/src/surfaces/grid-views.ts +15 -18
  422. package/src/surfaces/inspector-dock.ts +13 -12
  423. package/src/surfaces/jump-bar.ts +5 -6
  424. package/src/surfaces/jxsuite-update.ts +16 -22
  425. package/src/surfaces/library-pane.ts +19 -20
  426. package/src/surfaces/logic-panel.ts +17 -30
  427. package/src/surfaces/logic-workspace.ts +13 -15
  428. package/src/surfaces/media-browser.ts +11 -10
  429. package/src/surfaces/media-field.ts +4 -5
  430. package/src/surfaces/media-pane.ts +8 -7
  431. package/src/surfaces/menu.ts +29 -23
  432. package/src/surfaces/navigator-dock.ts +11 -12
  433. package/src/surfaces/new-project.ts +27 -26
  434. package/src/surfaces/pane-context.ts +20 -25
  435. package/src/surfaces/pane-grid.ts +15 -10
  436. package/src/surfaces/panel-activity.ts +5 -6
  437. package/src/surfaces/panel-data.ts +3 -4
  438. package/src/surfaces/panel-deploy-checklist.ts +5 -6
  439. package/src/surfaces/panel-elements.ts +5 -7
  440. package/src/surfaces/panel-i18n.ts +5 -7
  441. package/src/surfaces/panel-imports.ts +6 -13
  442. package/src/surfaces/panel-outline.ts +25 -19
  443. package/src/surfaces/panel-page.ts +11 -18
  444. package/src/surfaces/panel-problems.ts +5 -7
  445. package/src/surfaces/panel-signals.ts +20 -34
  446. package/src/surfaces/panel-stylebook-layers.ts +5 -8
  447. package/src/surfaces/preferences.ts +21 -11
  448. package/src/surfaces/progress-modal.ts +15 -9
  449. package/src/surfaces/properties-panel.json +1 -1
  450. package/src/surfaces/properties-panel.ts +20 -42
  451. package/src/surfaces/publish.ts +18 -18
  452. package/src/surfaces/push-plan.ts +7 -8
  453. package/src/surfaces/rail.ts +13 -13
  454. package/src/surfaces/reference-field.ts +11 -15
  455. package/src/surfaces/schema-builder.ts +16 -22
  456. package/src/surfaces/schema-form.ts +15 -25
  457. package/src/surfaces/secret-field.ts +9 -6
  458. package/src/surfaces/seo.ts +21 -15
  459. package/src/surfaces/settings-contexts.ts +9 -7
  460. package/src/surfaces/settings-contributed.ts +14 -10
  461. package/src/surfaces/settings-css-vars.ts +5 -12
  462. package/src/surfaces/settings-defs.json +2 -2
  463. package/src/surfaces/settings-defs.ts +17 -21
  464. package/src/surfaces/settings-deploy.ts +8 -15
  465. package/src/surfaces/settings-extensions.ts +5 -6
  466. package/src/surfaces/settings-head.ts +33 -39
  467. package/src/surfaces/settings-locales.ts +8 -20
  468. package/src/surfaces/settings-overview.ts +5 -6
  469. package/src/surfaces/settings-packages.ts +8 -7
  470. package/src/surfaces/settings-pane.ts +9 -18
  471. package/src/surfaces/settings-rawjson.ts +5 -6
  472. package/src/surfaces/shell.ts +1 -2
  473. package/src/surfaces/slash-menu.ts +19 -9
  474. package/src/surfaces/statements.ts +13 -18
  475. package/src/surfaces/statusbar.ts +17 -14
  476. package/src/surfaces/style-panel.ts +18 -31
  477. package/src/surfaces/stylebook-chrome.ts +3 -5
  478. package/src/surfaces/tab-strip.ts +14 -13
  479. package/src/surfaces/target-line.ts +6 -7
  480. package/src/surfaces/welcome.ts +5 -7
  481. package/src/tabs/patch-ops.ts +4 -3
  482. package/src/tabs/project-config.ts +32 -21
  483. package/src/tabs/selection.ts +36 -8
  484. package/src/tabs/tab.ts +52 -41
  485. package/src/tabs/transact.ts +98 -53
  486. package/src/types.ts +32 -17
  487. package/src/ui/ai-credentials-form.ts +10 -13
  488. package/src/ui/ai-model-picker.ts +3 -3
  489. package/src/ui/cf-account-picker.ts +7 -9
  490. package/src/ui/color-selector.ts +9 -5
  491. package/src/ui/dynamic-slot.ts +7 -8
  492. package/src/ui/expression-editor.ts +112 -105
  493. package/src/ui/form-controls.ts +57 -48
  494. package/src/ui/formula-catalog.ts +239 -230
  495. package/src/ui/formula-chips.ts +33 -18
  496. package/src/ui/layers.ts +44 -31
  497. package/src/ui/media-picker.ts +18 -9
  498. package/src/ui/popover-surface.ts +20 -12
  499. package/src/ui/progress-modal.ts +13 -8
  500. package/src/ui/regions.ts +7 -6
  501. package/src/ui/schema-form.ts +113 -70
  502. package/src/ui/surface.ts +71 -8
  503. package/src/ui/timing.ts +9 -0
  504. package/src/ui/value-source.ts +44 -31
  505. package/src/ui/virtual-window.ts +3 -2
  506. package/src/utils/base64.ts +3 -1
  507. package/src/utils/edit-display.ts +73 -73
  508. package/src/utils/element-selectors.ts +3 -2
  509. package/src/utils/google-fonts.ts +15 -14
  510. package/src/utils/inherited-style.ts +18 -20
  511. package/src/utils/link-target.ts +1 -1
  512. package/src/utils/preview-format.ts +25 -3
  513. package/src/utils/strip-events.ts +49 -22
  514. package/src/utils/studio-utils.ts +29 -14
  515. package/src/view.ts +2 -3
  516. package/src/workspace/pane-derive.ts +10 -12
  517. package/src/workspace/session.ts +53 -43
  518. package/src/workspace/workspace.ts +40 -36
  519. package/dist/chunks/adapter-f93pafd7.js +0 -4
  520. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  521. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  522. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  523. package/dist/chunks/color-field-embq5ctg.js +0 -4
  524. package/dist/chunks/color-fpezvnkt.js +0 -4
  525. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  526. package/dist/chunks/combobox-773hdzyj.js +0 -4
  527. package/dist/chunks/components-ax2f1fnn.js +0 -4
  528. package/dist/chunks/content-source-108aqtk1.js +0 -4
  529. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  530. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  531. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  532. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  533. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  534. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  535. package/dist/chunks/files-44vp8a2s.js +0 -4
  536. package/dist/chunks/format-host-7q1petb9.js +0 -4
  537. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  538. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  539. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  540. package/dist/chunks/icons-p44xhjf0.js +0 -4
  541. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  542. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  543. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  544. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  545. package/dist/chunks/index-wkyfjeqz.js +0 -4
  546. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  547. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  548. package/dist/chunks/layers-xd92fg8d.js +0 -4
  549. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  550. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  551. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  552. package/dist/chunks/menu-37d07z9m.js +0 -4
  553. package/dist/chunks/menu-5c55ea3d.js +0 -4
  554. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  555. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  556. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  557. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  558. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  559. package/dist/chunks/parse-897fvqah.js +0 -4
  560. package/dist/chunks/platform-v1qctbe6.js +0 -4
  561. package/dist/chunks/popover-8htra4er.js +0 -4
  562. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  563. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  564. package/dist/chunks/references-gmqp82fs.js +0 -4
  565. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  566. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  567. package/dist/chunks/select-n3v7gwas.js +0 -4
  568. package/dist/chunks/split-pff8f3ze.js +0 -4
  569. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  570. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  571. package/dist/chunks/studio-1b04pd0j.js +0 -64
  572. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  573. package/dist/chunks/studio-4tanh828.js +0 -5
  574. package/dist/chunks/studio-55h4mstj.js +0 -4
  575. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  576. package/dist/chunks/studio-60dqgb0c.js +0 -5
  577. package/dist/chunks/studio-61dp09qg.js +0 -9
  578. package/dist/chunks/studio-63epcrj2.js +0 -5
  579. package/dist/chunks/studio-74k29dy9.js +0 -5
  580. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  581. package/dist/chunks/studio-7zx31knw.js +0 -9
  582. package/dist/chunks/studio-8bxk97km.js +0 -5
  583. package/dist/chunks/studio-933e30n4.js +0 -5
  584. package/dist/chunks/studio-98wnwhbg.js +0 -5
  585. package/dist/chunks/studio-9mccjwjh.js +0 -14
  586. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  587. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  588. package/dist/chunks/studio-e81q1vb9.js +0 -5
  589. package/dist/chunks/studio-epgrmqqm.js +0 -5
  590. package/dist/chunks/studio-ery42sqr.js +0 -4
  591. package/dist/chunks/studio-g1shz58g.js +0 -5
  592. package/dist/chunks/studio-gf0fz03c.js +0 -5
  593. package/dist/chunks/studio-gjtpe62q.js +0 -6
  594. package/dist/chunks/studio-gkskhg7m.js +0 -5
  595. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  596. package/dist/chunks/studio-j03zga3y.js +0 -9
  597. package/dist/chunks/studio-jhpxeckz.js +0 -5
  598. package/dist/chunks/studio-k01r7ykp.js +0 -5
  599. package/dist/chunks/studio-kk7h30ne.js +0 -7
  600. package/dist/chunks/studio-kt1zqney.js +0 -5
  601. package/dist/chunks/studio-m3cwhvye.js +0 -5
  602. package/dist/chunks/studio-mcayt6hz.js +0 -5
  603. package/dist/chunks/studio-myjcghv3.js +0 -5
  604. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  605. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  606. package/dist/chunks/studio-nj5a01jy.js +0 -928
  607. package/dist/chunks/studio-pcgz8heb.js +0 -5
  608. package/dist/chunks/studio-qcsq0t15.js +0 -5
  609. package/dist/chunks/studio-qkstvve9.js +0 -5
  610. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  611. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  612. package/dist/chunks/studio-s8dmmz66.js +0 -5
  613. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  614. package/dist/chunks/studio-szsjbj0g.js +0 -5
  615. package/dist/chunks/studio-t1xzawhr.js +0 -16
  616. package/dist/chunks/studio-t6b6qe31.js +0 -5
  617. package/dist/chunks/studio-tdcprbqb.js +0 -5
  618. package/dist/chunks/studio-vyc0b4he.js +0 -10
  619. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  620. package/dist/chunks/studio-w3hskzqk.js +0 -5
  621. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  622. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  623. package/dist/chunks/studio-y6n42tgs.js +0 -5
  624. package/dist/chunks/studio-yb560vxr.js +0 -5
  625. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  626. package/dist/chunks/studio-yw05w8f0.js +0 -7
  627. package/dist/chunks/studio-z16sgavc.js +0 -5
  628. package/dist/chunks/studio-zyqn40w4.js +0 -5
  629. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  630. package/dist/chunks/tabs-jwthg40w.js +0 -4
  631. package/dist/chunks/textfield-spy3hc77.js +0 -4
  632. package/dist/chunks/toast-4d35zd64.js +0 -4
  633. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  634. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  635. package/dist/chunks/tree-h19v1jfz.js +0 -4
  636. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  637. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
@@ -38,6 +38,11 @@ export interface CloudSignal {
38
38
  project: CloudProject | null;
39
39
  }
40
40
 
41
+ declare global {
42
+ /** Published by the cloud shell's boot module before the studio bundle evaluates. */
43
+ var __jxCloud: CloudSignal | undefined;
44
+ }
45
+
41
46
  /**
42
47
  * Why Studio will not fall back to the dev-server adapter, most specific evidence first.
43
48
  *
@@ -86,13 +91,14 @@ const BACKENDLESS_SCHEMES: ReadonlySet<string> = new Set(["views:", "file:"]);
86
91
 
87
92
  /** Read the boot environment from the live globals and document. */
88
93
  export function bootEnvironment(): BootEnvironment {
89
- const doc = (globalThis as { document?: Document }).document;
94
+ // A DOM-less host (a test runner, a worker) has no document or location to read.
95
+ const doc = typeof document === "undefined" ? undefined : document;
90
96
  const meta = `meta[name="${BOOT_META.name}"][content="${BOOT_META.content}"]`;
91
97
  return {
92
- cloud: (globalThis as unknown as { __jxCloud?: CloudSignal }).__jxCloud != null,
98
+ cloud: globalThis.__jxCloud != null,
93
99
  declared: doc?.querySelector(meta) != null,
94
100
  launcher: launcherSignal(),
95
- protocol: (globalThis as { location?: Location }).location?.protocol ?? "",
101
+ protocol: typeof location === "undefined" ? "" : location.protocol,
96
102
  };
97
103
  }
98
104
 
@@ -159,6 +165,6 @@ export function resolveDefaultPlatform(): StudioPlatform {
159
165
  if (refusal) {
160
166
  throw new PlatformUnavailableError(refusal);
161
167
  }
162
- const cloud = (globalThis as unknown as { __jxCloud?: CloudSignal }).__jxCloud;
168
+ const cloud = globalThis.__jxCloud;
163
169
  return cloud ? createCloudPlatform(cloud.project) : createDevServerPlatform();
164
170
  }
@@ -13,9 +13,9 @@ import { canPickDirectory, pickDirectoryPath } from "../services/directory-picke
13
13
  import { negotiateCollab } from "@jxsuite/collab/negotiate";
14
14
  import type { CollabNegotiation } from "@jxsuite/collab/negotiate";
15
15
  import type { WsCollabConnection } from "@jxsuite/collab/client";
16
- import type { ProjectConfig } from "@jxsuite/schema/types";
16
+ import { isFunction } from "@jxsuite/schema/guards";
17
+ import type { JsonObject, JsonValue, JxMutableNode, ProjectConfig } from "@jxsuite/schema/types";
17
18
  import type {
18
- CreateProjectDestination,
19
19
  DataConnectionsResponse,
20
20
  DataConnectionTestResult,
21
21
  DataPushResult,
@@ -35,20 +35,22 @@ import type {
35
35
  ProjectSchemasResponse,
36
36
  ReferencesResult,
37
37
  RenameResult,
38
- SecretsSetRequest,
38
+ KeyValuePatch,
39
39
  SecretsSetResponse,
40
40
  SiteBuildResult,
41
41
  SitePreviewResult,
42
42
  StarterInfo,
43
+ StudioPlatform,
43
44
  } from "../types";
44
45
  import { problemDetail, problemMessage } from "@jxsuite/protocol";
46
+ import type { CfProxyEnvelope } from "./cloud";
45
47
  import type { UploadResult } from "@jxsuite/protocol";
46
48
 
47
- /** A directory entry from the server, tolerating extra wire fields. */
48
- type WireDirEntry = DirEntry & Record<string, unknown>;
49
-
50
49
  /** Parse a fetch Response body as JSON, asserting the expected shape at the boundary. */
51
50
  async function readJson<T>(res: Response): Promise<T> {
51
+ /* SAFETY: every route read here is a `/__studio/*` route of @jxsuite/server (specs/server.md §4),
52
+ whose replies have the shapes ../types and the wire interfaces in this file describe, and each
53
+ caller names the type of the route it called. */
52
54
  return (await res.json()) as T;
53
55
  }
54
56
 
@@ -56,11 +58,46 @@ interface ErrorBody {
56
58
  error?: string;
57
59
  }
58
60
 
61
+ /** One entry of the `/__studio/sites` glob: a site's folder and its parsed project.json. */
59
62
  interface SiteEntry {
60
- config: unknown;
63
+ config: ProjectConfig | null;
61
64
  path: string;
62
65
  }
63
66
 
67
+ /**
68
+ * `GET /__studio/project-info`: what the server knows about a folder. The route sends more than
69
+ * Studio reads (`projectRoot` among them), and those members ride along untouched.
70
+ */
71
+ interface ProjectInfoReply {
72
+ isSiteProject: boolean;
73
+ projectConfig?: ProjectConfig | null;
74
+ directories?: string[];
75
+ [member: string]: JsonValue | ProjectConfig | undefined;
76
+ }
77
+
78
+ /** The body of an `fs` event on the `/__reload` stream (the server's watcher batches them). */
79
+ interface FsEventBatch {
80
+ events?: FsEvent[];
81
+ }
82
+
83
+ /** `showDirectoryPicker()` (WICG File System Access), which only Chromium-based browsers expose. */
84
+ type ShowDirectoryPicker = (options: { mode: string }) => Promise<FileSystemDirectoryHandle>;
85
+
86
+ /** True when the window implements the File System Access directory picker. */
87
+ function hasDirectoryPicker(
88
+ host: Window,
89
+ ): host is Window & { showDirectoryPicker: ShowDirectoryPicker } {
90
+ return "showDirectoryPicker" in host && isFunction(host.showDirectoryPicker);
91
+ }
92
+
93
+ /** The options object {@link StudioPlatform.createProject} takes. */
94
+ type CreateProjectOptions = Parameters<StudioPlatform["createProject"]>[0];
95
+
96
+ /** What a row insert or update answers: the row as stored. */
97
+ interface DataRowWrite {
98
+ row: JsonObject;
99
+ }
100
+
64
101
  /**
65
102
  * Create a DevServerPlatform instance.
66
103
  *
@@ -117,7 +154,7 @@ export function createDevServerPlatform() {
117
154
  method: "POST",
118
155
  });
119
156
  if (!res.ok) {
120
- const body = (await readJson<ErrorBody>(res).catch(() => ({}))) as ErrorBody;
157
+ const body = await readJson<ErrorBody>(res).catch((): ErrorBody => ({}));
121
158
  throw new Error(
122
159
  `Could not open ${root}: ${problemDetail(body) ?? `activation failed (${res.status})`}`,
123
160
  );
@@ -134,7 +171,7 @@ export function createDevServerPlatform() {
134
171
  if (!_projectRoot) {
135
172
  return;
136
173
  }
137
- _activation = postActivate(_projectRoot).catch((error: unknown) => {
174
+ _activation = postActivate(_projectRoot).catch((error) => {
138
175
  console.error("Project re-activation failed:", error);
139
176
  });
140
177
  }
@@ -171,6 +208,36 @@ export function createDevServerPlatform() {
171
208
  return p.startsWith(`${_projectRoot}/`) ? p.slice(_projectRoot.length + 1) : p;
172
209
  }
173
210
 
211
+ /**
212
+ * Native folder chooser for the New Project modal's Browse… button. Present only when the browser
213
+ * implements `showDirectoryPicker` (Chromium-based); elsewhere the member stays undefined and the
214
+ * modal falls back to a typed Location field.
215
+ *
216
+ * The picked handle carries no filesystem path, so it is resolved by the id the picker tags the
217
+ * folder with (see `@jxsuite/studio/directory-picker`). Resolves `null` only when the user
218
+ * dismisses the chooser; every other failure rejects with a sentence the modal shows under
219
+ * Location. So `locate` keeps the helper's contract: `null` is "no folder holds this id" (the
220
+ * route's 200 `{ path: null }`), and a non-ok answer throws the problem the server sent rather
221
+ * than posing as a miss. A network failure (`TypeError: Failed to fetch`, e.g. a page that is not
222
+ * being served by the dev server at all) propagates as is, and the picker names it.
223
+ */
224
+ const directoryPicking: Pick<StudioPlatform, "pickDirectory"> = {};
225
+ if (canPickDirectory()) {
226
+ directoryPicking.pickDirectory = async (): Promise<string | null> =>
227
+ pickDirectoryPath(async ({ id, name }) => {
228
+ const res = await fetch(
229
+ `/__studio/locate-directory?name=${encodeURIComponent(name)}&id=${encodeURIComponent(id)}`,
230
+ );
231
+ if (!res.ok) {
232
+ // A proxy, or a `views://` host with no dev server behind it, may answer in HTML.
233
+ const body = await readJson<JsonValue>(res).catch(() => null);
234
+ throw new Error(problemMessage(body, res.status));
235
+ }
236
+ const found = await readJson<{ path?: string | null }>(res);
237
+ return found.path ?? null;
238
+ });
239
+ }
240
+
174
241
  return {
175
242
  id: "devserver",
176
243
 
@@ -189,7 +256,7 @@ export function createDevServerPlatform() {
189
256
  // Fire-and-forget: callers that need the binding in place before reading await activate()
190
257
  // Themselves. The rejection is reported rather than dropped — an unactivated root leaves
191
258
  // Every rootless endpoint (git especially) operating on the server's OWN root.
192
- _activation = this.activate(_projectRoot).catch((error: unknown) => {
259
+ _activation = this.activate(_projectRoot).catch((error) => {
193
260
  console.error("Project activation failed:", error);
194
261
  });
195
262
  }
@@ -213,17 +280,14 @@ export function createDevServerPlatform() {
213
280
 
214
281
  async openProject() {
215
282
  // Use Chrome's showDirectoryPicker API
216
- if (!("showDirectoryPicker" in window)) {
283
+ const host = window;
284
+ if (!hasDirectoryPicker(host)) {
217
285
  throw new Error("showDirectoryPicker not available — use a Chromium-based browser");
218
286
  }
219
287
 
220
288
  let dirHandle;
221
289
  try {
222
- dirHandle = await (
223
- window as unknown as {
224
- showDirectoryPicker: (opts: { mode: string }) => Promise<FileSystemDirectoryHandle>;
225
- }
226
- ).showDirectoryPicker({ mode: "readwrite" });
290
+ dirHandle = await host.showDirectoryPicker({ mode: "readwrite" });
227
291
  } catch (error) {
228
292
  // User cancelled the picker
229
293
  if (error instanceof Error && error.name === "AbortError") {
@@ -241,6 +305,9 @@ export function createDevServerPlatform() {
241
305
  }
242
306
 
243
307
  const file = await siteHandle.getFile();
308
+ /* SAFETY: the user picked this folder as a project, and project.json is that project's own
309
+ config file; it is matched below against the server's parse of the same file, and every
310
+ adapter hands project.json to Studio as the ProjectConfig the session edits. */
244
311
  const config = JSON.parse(await file.text()) as ProjectConfig;
245
312
 
246
313
  // Resolve server-relative path by matching against known sites
@@ -297,12 +364,7 @@ export function createDevServerPlatform() {
297
364
  ? await readJson<{ name: string; root: string }>(projectRes)
298
365
  : { name: "project", root: "." };
299
366
  const info = infoRes.ok
300
- ? await readJson<{
301
- isSiteProject: boolean;
302
- projectConfig?: ProjectConfig | null;
303
- directories?: string[];
304
- [key: string]: unknown;
305
- }>(infoRes)
367
+ ? await readJson<ProjectInfoReply>(infoRes)
306
368
  : { isSiteProject: false };
307
369
  return { info, meta };
308
370
  } catch {
@@ -315,27 +377,8 @@ export function createDevServerPlatform() {
315
377
  /**
316
378
  * Scaffold a project at `destination.parent/directory`. The dev server refuses the request
317
379
  * outright when no destination is supplied — it will not fall back to its own root.
318
- *
319
- * @param {{
320
- * name: string;
321
- * description?: string;
322
- * url?: string;
323
- * adapter?: string;
324
- * directory: string;
325
- * destination: CreateProjectDestination;
326
- * }} opts
327
380
  */
328
- async createProject(opts: {
329
- name: string;
330
- description?: string;
331
- url?: string;
332
- adapter?: string;
333
- directory: string;
334
- destination: CreateProjectDestination;
335
- starter?: string;
336
- template?: string;
337
- design?: Record<string, unknown>;
338
- }) {
381
+ async createProject(opts: CreateProjectOptions) {
339
382
  const res = await fetch("/__studio/create-project", {
340
383
  body: JSON.stringify(opts),
341
384
  headers: { "Content-Type": "application/json" },
@@ -348,37 +391,7 @@ export function createDevServerPlatform() {
348
391
  return await res.json();
349
392
  },
350
393
 
351
- /**
352
- * Native folder chooser for the New Project modal's Browse… button. Present only when the
353
- * browser implements `showDirectoryPicker` (Chromium-based); elsewhere the member stays
354
- * undefined and the modal falls back to a typed Location field.
355
- *
356
- * The picked handle carries no filesystem path, so it is resolved by the id the picker tags the
357
- * folder with (see `@jxsuite/studio/directory-picker`). Resolves `null` only when the user
358
- * dismisses the chooser; every other failure rejects with a sentence the modal shows under
359
- * Location. So `locate` keeps the helper's contract: `null` is "no folder holds this id" (the
360
- * route's 200 `{ path: null }`), and a non-ok answer throws the problem the server sent rather
361
- * than posing as a miss. A network failure (`TypeError: Failed to fetch`, e.g. a page that is
362
- * not being served by the dev server at all) propagates as is, and the picker names it.
363
- */
364
- ...(canPickDirectory()
365
- ? {
366
- async pickDirectory(): Promise<string | null> {
367
- return pickDirectoryPath(async ({ id, name }) => {
368
- const res = await fetch(
369
- `/__studio/locate-directory?name=${encodeURIComponent(name)}&id=${encodeURIComponent(id)}`,
370
- );
371
- if (!res.ok) {
372
- // A proxy, or a `views://` host with no dev server behind it, may answer in HTML.
373
- const body: unknown = await res.json().catch(() => null);
374
- throw new Error(problemMessage(body, res.status));
375
- }
376
- const found = await readJson<{ path?: string | null }>(res);
377
- return found.path ?? null;
378
- });
379
- },
380
- }
381
- : {}),
394
+ ...directoryPicking,
382
395
 
383
396
  /** List starter templates from the dev server. */
384
397
  async listStarters(): Promise<StarterInfo[]> {
@@ -407,7 +420,7 @@ export function createDevServerPlatform() {
407
420
  if (!res.ok) {
408
421
  throw new Error(`Failed to list directory: ${dir}`);
409
422
  }
410
- const entries = await readJson<WireDirEntry[]>(res);
423
+ const entries = await readJson<DirEntry[]>(res);
411
424
  for (const e of entries) {
412
425
  e.path = stripRoot(e.path);
413
426
  }
@@ -465,10 +478,14 @@ export function createDevServerPlatform() {
465
478
  if (!res.ok) {
466
479
  throw new Error(`Upload failed: ${path}`);
467
480
  }
468
- const body = (await res.json()) as Partial<UploadResult>;
481
+ const body = await readJson<Partial<UploadResult>>(res);
469
482
  // The dev server echoes the path today; falling back to the request keeps a backend that says
470
483
  // Nothing working rather than writing `undefined` into a document.
471
- return { path: body.path ?? path, ...(body.size === undefined ? {} : { size: body.size }) };
484
+ const uploaded: UploadResult = { path: body.path ?? path };
485
+ if (body.size !== undefined) {
486
+ uploaded.size = body.size;
487
+ }
488
+ return uploaded;
472
489
  },
473
490
 
474
491
  /** @param {string} path */
@@ -552,10 +569,12 @@ export function createDevServerPlatform() {
552
569
  options?.onResync?.("reconnect");
553
570
  }
554
571
  });
555
- es.addEventListener("fs", (ev: MessageEvent) => {
556
- let payload: { events?: FsEvent[] };
572
+ es.addEventListener("fs", (ev: MessageEvent<string>) => {
573
+ let payload: FsEventBatch;
557
574
  try {
558
- payload = JSON.parse(ev.data as string) as { events?: FsEvent[] };
575
+ /* SAFETY: `fs` events on /__reload are sent only by @jxsuite/server's watcher, as
576
+ broadcastEvent("fs", { events }) over its batched FsEvent buffer (server watch.ts). */
577
+ payload = JSON.parse(ev.data) as FsEventBatch;
559
578
  } catch {
560
579
  return;
561
580
  }
@@ -597,7 +616,7 @@ export function createDevServerPlatform() {
597
616
  }
598
617
  if (_collabProbe === null) {
599
618
  _collabProbe = fetch("/__studio/collab")
600
- .then(async (res) => (res.ok ? negotiateCollab(await res.json()) : null))
619
+ .then(async (res) => (res.ok ? negotiateCollab(await readJson<JsonValue>(res)) : null))
601
620
  .catch(() => null);
602
621
  }
603
622
  const negotiation = await _collabProbe;
@@ -694,7 +713,7 @@ export function createDevServerPlatform() {
694
713
  if (!res.ok) {
695
714
  return false;
696
715
  }
697
- const data = (await res.json()) as { needsInstall?: boolean };
716
+ const data = await readJson<{ needsInstall?: boolean }>(res);
698
717
  return Boolean(data.needsInstall);
699
718
  },
700
719
 
@@ -721,11 +740,8 @@ export function createDevServerPlatform() {
721
740
 
722
741
  // ─── Code services (optional) ─────────────────────────────────────────
723
742
 
724
- /**
725
- * @param {string} action
726
- * @param {unknown} payload
727
- */
728
- async codeService(action: string, payload: unknown) {
743
+ /** Run one code-service action on the server; null when the route fails or is absent. */
744
+ async codeService(action: string, payload: Parameters<StudioPlatform["codeService"]>[1]) {
729
745
  try {
730
746
  const res = await fetch(`/__studio/code/${action}`, {
731
747
  body: JSON.stringify(payload),
@@ -788,7 +804,7 @@ export function createDevServerPlatform() {
788
804
  if (!res.ok) {
789
805
  return [];
790
806
  }
791
- const entries = await readJson<WireDirEntry[]>(res);
807
+ const entries = await readJson<DirEntry[]>(res);
792
808
  for (const e of entries) {
793
809
  e.path = stripRoot(e.path);
794
810
  }
@@ -911,26 +927,26 @@ export function createDevServerPlatform() {
911
927
  return data;
912
928
  },
913
929
 
914
- async dataInsertRow(req: DataRowInsert): Promise<{ row: Record<string, unknown> }> {
930
+ async dataInsertRow(req: DataRowInsert): Promise<DataRowWrite> {
915
931
  const res = await fetch(`/__studio/data/rows?dir=${encodeURIComponent(serverPath("."))}`, {
916
932
  body: JSON.stringify(req),
917
933
  headers: { "Content-Type": "application/json" },
918
934
  method: "POST",
919
935
  });
920
- const data = await readJson<{ row: Record<string, unknown> } & ErrorBody>(res);
936
+ const data = await readJson<DataRowWrite & ErrorBody>(res);
921
937
  if (!res.ok) {
922
938
  throw new Error(problemDetail(data) ?? "Insert failed");
923
939
  }
924
940
  return data;
925
941
  },
926
942
 
927
- async dataUpdateRow(req: DataRowUpdate): Promise<{ row: Record<string, unknown> }> {
943
+ async dataUpdateRow(req: DataRowUpdate): Promise<DataRowWrite> {
928
944
  const res = await fetch(`/__studio/data/rows?dir=${encodeURIComponent(serverPath("."))}`, {
929
945
  body: JSON.stringify(req),
930
946
  headers: { "Content-Type": "application/json" },
931
947
  method: "PUT",
932
948
  });
933
- const data = await readJson<{ row: Record<string, unknown> } & ErrorBody>(res);
949
+ const data = await readJson<DataRowWrite & ErrorBody>(res);
934
950
  if (!res.ok) {
935
951
  throw new Error(problemDetail(data) ?? "Update failed");
936
952
  }
@@ -966,7 +982,7 @@ export function createDevServerPlatform() {
966
982
  },
967
983
 
968
984
  /** Write/remove secrets in the dev server's .dev.vars; names-only response. */
969
- async setSecrets(req: SecretsSetRequest): Promise<SecretsSetResponse> {
985
+ async setSecrets(req: KeyValuePatch): Promise<SecretsSetResponse> {
970
986
  const res = await fetch(`/__studio/secrets?dir=${encodeURIComponent(serverPath("."))}`, {
971
987
  body: JSON.stringify(req),
972
988
  headers: { "Content-Type": "application/json" },
@@ -982,15 +998,17 @@ export function createDevServerPlatform() {
982
998
  /**
983
999
  * Invoke a format capability (parse/serialize) server-side.
984
1000
  *
985
- * @param {Record<string, unknown>} payload — { format, action, source?, doc?, options? }
1001
+ * @param payload — { format, action, source?, doc?, options? }
986
1002
  */
987
- async formatAction(payload: Record<string, unknown>) {
1003
+ async formatAction(payload: Parameters<NonNullable<StudioPlatform["formatAction"]>>[0]) {
988
1004
  const res = await fetch("/__studio/format", {
989
1005
  body: JSON.stringify({ ...payload, dir: serverPath(".") }),
990
1006
  headers: { "Content-Type": "application/json" },
991
1007
  method: "POST",
992
1008
  });
993
- const data = await readJson<{ error?: string; result?: unknown }>(res);
1009
+ /* The format route answers `{ result }` on success (the document a format class's `parse`
1010
+ built, or the text its `serialize` wrote) and a problem document otherwise. */
1011
+ const data = await readJson<JsonObject & { result: JxMutableNode | string }>(res);
994
1012
  if (!res.ok) {
995
1013
  throw new Error(problemDetail(data) ?? "Format action failed");
996
1014
  }
@@ -1016,14 +1034,13 @@ export function createDevServerPlatform() {
1016
1034
  if (!res.ok) {
1017
1035
  return null;
1018
1036
  }
1019
- const { schema } = await readJson<{ schema: unknown }>(res);
1037
+ const { schema } = await readJson<{ schema: JsonValue }>(res);
1020
1038
  return schema;
1021
1039
  },
1022
1040
 
1023
1041
  // ─── Class resolution (dev-proxy) ─────────────────────────────────────
1024
1042
 
1025
- /** @param {Record<string, unknown>} body */
1026
- async resolveClass(body: Record<string, unknown>) {
1043
+ async resolveClass(body: Parameters<NonNullable<StudioPlatform["resolveClass"]>>[0]) {
1027
1044
  const res = await fetch("/__jx_resolve__", {
1028
1045
  body: JSON.stringify(body),
1029
1046
  headers: { "content-type": "application/json" },
@@ -1032,7 +1049,7 @@ export function createDevServerPlatform() {
1032
1049
  if (!res.ok) {
1033
1050
  throw new Error(`Class resolution failed: ${res.status}`);
1034
1051
  }
1035
- return await readJson<unknown>(res);
1052
+ return await readJson<JsonValue>(res);
1036
1053
  },
1037
1054
 
1038
1055
  // ─── Git operations ──────────────────────────────────────────────────
@@ -1229,7 +1246,7 @@ export function createDevServerPlatform() {
1229
1246
  const body = await readJson<ErrorBody>(res);
1230
1247
  throw new Error(problemDetail(body) ?? "The site could not be built.");
1231
1248
  }
1232
- return (await res.json()) as SiteBuildResult;
1249
+ return await readJson<SiteBuildResult>(res);
1233
1250
  },
1234
1251
 
1235
1252
  /**
@@ -1248,7 +1265,7 @@ export function createDevServerPlatform() {
1248
1265
  const body = await readJson<ErrorBody>(res);
1249
1266
  throw new Error(problemDetail(body) ?? "The site could not be previewed.");
1250
1267
  }
1251
- return (await res.json()) as SitePreviewResult;
1268
+ return await readJson<SitePreviewResult>(res);
1252
1269
  },
1253
1270
 
1254
1271
  async setPreviewOverlay(path: string, contents: string) {
@@ -1300,12 +1317,7 @@ export function createDevServerPlatform() {
1300
1317
  headers: { "Content-Type": "application/json", "X-CF-Token": token },
1301
1318
  body: JSON.stringify({ path: apiPath, method: init?.method ?? "GET", body: init?.body }),
1302
1319
  });
1303
- const envelope = (await res.json()) as {
1304
- success?: boolean;
1305
- result?: unknown;
1306
- errors?: { message: string }[];
1307
- error?: string;
1308
- };
1320
+ const envelope = await readJson<CfProxyEnvelope>(res);
1309
1321
  if (!res.ok || envelope.success === false) {
1310
1322
  const message =
1311
1323
  envelope.errors?.map((e) => e.message).join("; ") ?? envelope.error ?? res.statusText;
@@ -1322,10 +1334,13 @@ export function createDevServerPlatform() {
1322
1334
  return null;
1323
1335
  }
1324
1336
  try {
1325
- const accounts = (await this.cfApi?.("/accounts")) as { id: string; name: string }[];
1326
- if (!accounts?.length) {
1337
+ const result = await this.cfApi("/accounts");
1338
+ if (!Array.isArray(result) || result.length === 0) {
1327
1339
  return { connected: false };
1328
1340
  }
1341
+ /* SAFETY: cfApi resolved the v4 envelope's `result`, and Cloudflare documents GET /accounts
1342
+ as answering an array of account objects, each with a string `id` and `name`. */
1343
+ const accounts = result as { id: string; name: string }[];
1329
1344
  const chosen = accounts.find((a) => a.id === getCfAccountId()) ?? accounts[0]!;
1330
1345
  setCfAccountId(chosen.id);
1331
1346
  return { connected: true, accountId: chosen.id, accountName: chosen.name };
@@ -1343,14 +1358,11 @@ export function createDevServerPlatform() {
1343
1358
  return [];
1344
1359
  }
1345
1360
  const sites = await readJson<SiteEntry[]>(res);
1346
- return sites.map((site) => {
1347
- const config = site.config as { name?: string } | null;
1348
- return {
1349
- name: config?.name || site.path.split("/").at(-1) || site.path,
1350
- root: site.path,
1351
- description: site.path,
1352
- };
1353
- });
1361
+ return sites.map((site) => ({
1362
+ name: site.config?.name || site.path.split("/").at(-1) || site.path,
1363
+ root: site.path,
1364
+ description: site.path,
1365
+ }));
1354
1366
  },
1355
1367
 
1356
1368
  // ─── AI Assistant (Stack B: OpenAI-compatible SSE proxy) ───────────────────
@@ -21,6 +21,7 @@
21
21
 
22
22
  import { READ_FILES_MAX_PATHS } from "@jxsuite/protocol";
23
23
  import type { ReadFilesResult } from "@jxsuite/protocol";
24
+ import { isNonNullObject, isString } from "@jxsuite/schema/guards";
24
25
 
25
26
  /**
26
27
  * What one batch request came back as.
@@ -57,14 +58,20 @@ export interface ReadBatcher {
57
58
 
58
59
  interface Waiter {
59
60
  resolve: (content: string) => void;
60
- reject: (error: unknown) => void;
61
+ /** Rejects with whatever the transport or `fetchOne` rejected with, unchanged. */
62
+ reject: (cause: unknown) => void;
61
63
  }
62
64
 
63
65
  /** Path → every caller waiting on it. Same-path reads in one window share ONE request and result. */
64
66
  type Pending = Map<string, Waiter[]>;
65
67
 
66
- function isObject(value: unknown): value is object {
67
- return typeof value === "object" && value !== null;
68
+ /**
69
+ * A row's outcome as the batcher reads it. Every protocol outcome fits it, but the rows come off
70
+ * the wire unchecked, so `content` may be any value and either member may be missing.
71
+ */
72
+ interface WireOutcome {
73
+ content?: unknown;
74
+ error?: { message?: string } | undefined;
68
75
  }
69
76
 
70
77
  /**
@@ -108,7 +115,7 @@ export function createReadBatcher(options: ReadBatcherOptions): ReadBatcher {
108
115
  waiter.resolve(content);
109
116
  }
110
117
  },
111
- (error: unknown) => {
118
+ (error) => {
112
119
  for (const waiter of waiters) {
113
120
  waiter.reject(error);
114
121
  }
@@ -182,7 +189,7 @@ export function createReadBatcher(options: ReadBatcherOptions): ReadBatcher {
182
189
  }
183
190
  /* Anything that is not an object cannot be a ReadFilesResult (a `null` body, a bare string).
184
191
  The route did not answer this chunk, so it is served singly — the same as a failed call. */
185
- if (answer === "retry-singly" || answer === "unsupported" || !isObject(answer)) {
192
+ if (answer === "retry-singly" || answer === "unsupported" || !isNonNullObject(answer)) {
186
193
  if (answer === "unsupported") {
187
194
  batching = false;
188
195
  }
@@ -213,14 +220,15 @@ export function createReadBatcher(options: ReadBatcherOptions): ReadBatcher {
213
220
  }
214
221
  chunk.delete(path);
215
222
  answered += 1;
216
- if (typeof (outcome as { content?: unknown } | undefined)?.content === "string") {
217
- const { content } = outcome as { content: string };
223
+ const wire: WireOutcome | undefined = outcome;
224
+ const content = wire?.content;
225
+ if (isString(content)) {
218
226
  for (const waiter of waiters) {
219
227
  waiter.resolve(content);
220
228
  }
221
229
  } else {
222
230
  // Per path: one missing file (404), one binary file (415) fails ITS readers and no others.
223
- const message = (outcome as { error?: { message?: string } } | undefined)?.error?.message;
231
+ const message = wire?.error?.message;
224
232
  const error = new Error(message || `Failed to read file: ${path}`);
225
233
  for (const waiter of waiters) {
226
234
  waiter.reject(error);
@@ -3,6 +3,7 @@
3
3
  * member (dev server sites, cloud platforms). Hydrated once at boot (studio.ts) like the
4
4
  * recent-projects cache; the welcome screen reads it synchronously.
5
5
  */
6
+ import { isFunction } from "@jxsuite/schema/guards";
6
7
  import { getPlatform, hasPlatform } from "./platform";
7
8
  import type { ProjectListEntry } from "./types";
8
9
 
@@ -10,7 +11,7 @@ let cache: ProjectListEntry[] = [];
10
11
 
11
12
  /** True when the active platform exposes a project catalogue. */
12
13
  export function platformListsProjects(): boolean {
13
- return hasPlatform() && typeof getPlatform().listProjects === "function";
14
+ return hasPlatform() && isFunction(getPlatform().listProjects);
14
15
  }
15
16
 
16
17
  /** Refresh the cache from the platform; resolves to [] when unsupported or failing. */
@@ -75,7 +75,7 @@ export interface DeployStep {
75
75
 
76
76
  /** The active project's configuration, or null when no project is open. */
77
77
  function currentConfig(): ProjectConfig | null {
78
- return (projectState?.projectConfig as ProjectConfig | undefined) ?? null;
78
+ return projectState?.projectConfig ?? null;
79
79
  }
80
80
 
81
81
  /**
@@ -152,6 +152,11 @@ function repoStep(): DeployStep {
152
152
  };
153
153
  }
154
154
 
155
+ /** The remotes a host's git status actually carries: a host may omit the array altogether. */
156
+ interface ReportedRemotes {
157
+ remotes?: string[] | undefined;
158
+ }
159
+
155
160
  function remoteStep(): DeployStep {
156
161
  const { status } = shell.git;
157
162
  if (status === null || !status.isRepo) {
@@ -165,7 +170,8 @@ function remoteStep(): DeployStep {
165
170
  }
166
171
  // A GitStatus from a host that reports no remotes array is not a repo with remotes — it is a
167
172
  // Host that did not say. Reading through it took the whole status bar down with a TypeError.
168
- if ((status.remotes ?? []).length === 0) {
173
+ const reported: ReportedRemotes = status;
174
+ if ((reported.remotes ?? []).length === 0) {
169
175
  return {
170
176
  command: "git.createGithubRepository",
171
177
  detail: "This repository is local only — nothing outside this machine can build it.",