@jxsuite/studio 6.1.1 → 8.0.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 (785) hide show
  1. package/README.md +5 -5
  2. package/dist/chunks/2020-5wtzce5g.js +4 -0
  3. package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
  4. package/dist/chunks/adapter-5tphg7xe.js +4 -0
  5. package/dist/chunks/add-new-flow-psym14sn.js +4 -0
  6. package/dist/chunks/cf-account-picker-haqazq5r.js +4 -0
  7. package/dist/chunks/cf-settings-h2wrh6hq.js +4 -0
  8. package/dist/chunks/color-area-6rbra5dy.js +4 -0
  9. package/dist/chunks/color-field-gy56c94g.js +4 -0
  10. package/dist/chunks/color-m7r1vk54.js +4 -0
  11. package/dist/chunks/color-slider-sqqdyf6c.js +4 -0
  12. package/dist/chunks/combobox-72h32ejk.js +4 -0
  13. package/dist/chunks/components-r22xca09.js +4 -0
  14. package/dist/chunks/content-source-mmppmcyg.js +4 -0
  15. package/dist/chunks/convert-to-repeater-he70fc2b.js +4 -0
  16. package/dist/chunks/dialog-c4x05vyx.js +4 -0
  17. package/dist/chunks/editor-ccd9jwsa.js +4 -0
  18. package/dist/chunks/entry-commands-6qxz9e8p.js +4 -0
  19. package/dist/chunks/extension-sections-0egb88dm.js +4 -0
  20. package/dist/chunks/file-ops-qnab36ek.js +4 -0
  21. package/dist/chunks/files-rcn56qvm.js +4 -0
  22. package/dist/chunks/format-host-yxz0kjjs.js +4 -0
  23. package/dist/chunks/fs-events-d1qxq4z4.js +4 -0
  24. package/dist/chunks/grid-open-4z1g062t.js +4 -0
  25. package/dist/chunks/grid-view-qg1b5eqx.js +51 -0
  26. package/dist/chunks/icons-63bjtbs7.js +4 -0
  27. package/dist/chunks/iframe-entry-2zggzajv.js +5 -0
  28. package/dist/chunks/iframe-entry-76j8vwwx.js +5 -0
  29. package/dist/chunks/iframe-entry-99nr5zfb.js +5 -0
  30. package/dist/chunks/iframe-entry-pkgmcgp0.js +5 -0
  31. package/dist/chunks/iframe-host-ssv7kyj0.js +4 -0
  32. package/dist/chunks/{index-2veqmnhr.js → index-32eqzv1k.js} +3 -3
  33. package/dist/chunks/index-f0jn7nnp.js +4 -0
  34. package/dist/chunks/{javascript-8nbvs12s.js → javascript-pjp734q4.js} +3 -3
  35. package/dist/chunks/jsonMode-njkvsa02.js +13 -0
  36. package/dist/chunks/jx-validate-ttasrbh7.js +4 -0
  37. package/dist/chunks/layers-bgyr11tr.js +4 -0
  38. package/dist/chunks/layers-panel-7ez66zeq.js +4 -0
  39. package/dist/chunks/listbox-c421cf8c.js +4 -0
  40. package/dist/chunks/lit-html-v9gh687x.js +4 -0
  41. package/dist/chunks/media-library-sq468wts.js +4 -0
  42. package/dist/chunks/media-picker-shfe59pt.js +4 -0
  43. package/dist/chunks/menu-bdpzbfvs.js +4 -0
  44. package/dist/chunks/monaco-binding-vq1hgnn0.js +4 -0
  45. package/dist/chunks/monaco-buffer-3afgwvbp.js +4 -0
  46. package/dist/chunks/monaco-setup-xrd2cbkp.js +4 -0
  47. package/dist/chunks/notify-kzrjr3fv.js +4 -0
  48. package/dist/chunks/number-field-y62xq0ty.js +4 -0
  49. package/dist/chunks/parse-v77xtwv7.js +4 -0
  50. package/dist/chunks/platform-7v4rtd7m.js +4 -0
  51. package/dist/chunks/popover-b89sfej7.js +4 -0
  52. package/dist/chunks/publish-panel-2z9gw8ee.js +4 -0
  53. package/dist/chunks/publish-quick-qx2455cj.js +4 -0
  54. package/dist/chunks/publish-workspace-wrc1dgwx.js +4 -0
  55. package/dist/chunks/quick-search-n0t0eqxb.js +4 -0
  56. package/dist/chunks/references-9547rg5s.js +4 -0
  57. package/dist/chunks/right-panel-wsgnr9pn.js +4 -0
  58. package/dist/chunks/select-rzds841e.js +4 -0
  59. package/dist/chunks/source-control-kwktr9y6.js +4 -0
  60. package/dist/chunks/split-c9zfdgxf.js +4 -0
  61. package/dist/chunks/studio-03ct6yfv.js +9 -0
  62. package/dist/chunks/studio-07rcfje3.js +5 -0
  63. package/dist/chunks/studio-3e54qh39.js +7 -0
  64. package/dist/chunks/studio-3exxhz5g.js +5 -0
  65. package/dist/chunks/studio-3q40e3rj.js +5 -0
  66. package/dist/chunks/studio-3qeh9t0h.js +6 -0
  67. package/dist/chunks/studio-3qqjeep5.js +6 -0
  68. package/dist/chunks/studio-43sd2mam.js +4 -0
  69. package/dist/chunks/studio-4hp8pkyt.js +5 -0
  70. package/dist/chunks/studio-58xg6j2q.js +9 -0
  71. package/dist/chunks/studio-5g0rprdt.js +7 -0
  72. package/dist/chunks/studio-6m380wp7.js +5 -0
  73. package/dist/chunks/studio-80jyh1xh.js +4 -0
  74. package/dist/chunks/studio-83mk4bgg.js +9 -0
  75. package/dist/chunks/{studio-kggey1jt.js → studio-881z1xrx.js} +4 -4
  76. package/dist/chunks/studio-8m0y2qe7.js +5 -0
  77. package/dist/chunks/studio-8tr6cfrc.js +5 -0
  78. package/dist/chunks/studio-8vcvfs7r.js +6 -0
  79. package/dist/chunks/studio-9tmebf0s.js +5 -0
  80. package/dist/chunks/studio-a2bvaptz.js +5 -0
  81. package/dist/chunks/studio-b7y5mr30.js +5 -0
  82. package/dist/chunks/studio-bavb31r0.js +5 -0
  83. package/dist/chunks/studio-bbe4c90a.js +5 -0
  84. package/dist/chunks/studio-c05wdnt3.js +5 -0
  85. package/dist/chunks/studio-ccv2svc6.js +5 -0
  86. package/dist/chunks/studio-d5grtb9e.js +16 -0
  87. package/dist/chunks/studio-df0baea9.js +5 -0
  88. package/dist/chunks/studio-dgk4dqtx.js +7 -0
  89. package/dist/chunks/studio-e1g64q43.js +5 -0
  90. package/dist/chunks/studio-ed1hp6zf.js +6 -0
  91. package/dist/chunks/studio-ed3xx40h.js +7 -0
  92. package/dist/chunks/studio-f14e1zdj.js +5 -0
  93. package/dist/chunks/studio-fbhxxc5f.js +5 -0
  94. package/dist/chunks/studio-fyh0jc96.js +5 -0
  95. package/dist/chunks/studio-gcxk20n7.js +5 -0
  96. package/dist/chunks/studio-jaaz8ce9.js +5 -0
  97. package/dist/chunks/{studio-8grwxtqk.js → studio-jcnsdaep.js} +4 -4
  98. package/dist/chunks/studio-jsgf2q5k.js +7 -0
  99. package/dist/chunks/{studio-1q1sh2ax.js → studio-k3xxbagr.js} +3 -3
  100. package/dist/chunks/studio-k7evxqh4.js +5 -0
  101. package/dist/chunks/studio-kt3pjkwd.js +5 -0
  102. package/dist/chunks/studio-m8g16bgz.js +5 -0
  103. package/dist/chunks/studio-mn0476ag.js +5 -0
  104. package/dist/chunks/studio-mx1smyq0.js +5 -0
  105. package/dist/chunks/studio-n0c5h6mf.js +5 -0
  106. package/dist/chunks/{studio-rv11kfwa.js → studio-nh6d342n.js} +7 -7
  107. package/dist/chunks/studio-nqxqf8p2.js +4 -0
  108. package/dist/chunks/studio-p4nrkvqr.js +5 -0
  109. package/dist/chunks/{studio-h46vtzk8.js → studio-pbxa5fpc.js} +4 -4
  110. package/dist/chunks/studio-pgmvdv7z.js +7 -0
  111. package/dist/chunks/studio-ph84avkf.js +5 -0
  112. package/dist/chunks/{studio-wszjyh0j.js → studio-q0mvbaq6.js} +4 -4
  113. package/dist/chunks/studio-q0tccd43.js +5 -0
  114. package/dist/chunks/studio-q7rtx6zq.js +14 -0
  115. package/dist/chunks/{studio-pre0skq6.js → studio-qgh13jtz.js} +4 -4
  116. package/dist/chunks/studio-qmn1xc24.js +5 -0
  117. package/dist/chunks/studio-qwdqwkj0.js +5 -0
  118. package/dist/chunks/{studio-t6b6qe31.js → studio-r5qy30vx.js} +4 -4
  119. package/dist/chunks/studio-rj9eamf8.js +5 -0
  120. package/dist/chunks/studio-rptgsk96.js +5 -0
  121. package/dist/chunks/studio-rthyg42z.js +928 -0
  122. package/dist/chunks/studio-s19tp1xr.js +5 -0
  123. package/dist/chunks/studio-s32578pn.js +5 -0
  124. package/dist/chunks/studio-svb7yyve.js +5 -0
  125. package/dist/chunks/studio-syreb644.js +5 -0
  126. package/dist/chunks/studio-tf9jryb1.js +10 -0
  127. package/dist/chunks/studio-tfkznv39.js +5 -0
  128. package/dist/chunks/studio-tft6r105.js +5 -0
  129. package/dist/chunks/studio-txf2kysx.js +5 -0
  130. package/dist/chunks/studio-v8867ddv.js +12 -0
  131. package/dist/chunks/studio-vxq7fcvv.js +5 -0
  132. package/dist/chunks/studio-w4rz9hdk.js +5 -0
  133. package/dist/chunks/studio-wbcjbhy1.js +9 -0
  134. package/dist/chunks/studio-wc649wss.js +5 -0
  135. package/dist/chunks/studio-wys23mxz.js +5 -0
  136. package/dist/chunks/studio-x1x167jh.js +5 -0
  137. package/dist/chunks/studio-x9hsze61.js +5 -0
  138. package/dist/chunks/studio-y0n7yxea.js +9 -0
  139. package/dist/chunks/studio-y3ahhdpx.js +5 -0
  140. package/dist/chunks/studio-z97c48fk.js +5 -0
  141. package/dist/chunks/studio-zat62m0c.js +5 -0
  142. package/dist/chunks/studio-zcd2e7yz.js +5 -0
  143. package/dist/chunks/studio-zz9qe3rw.js +64 -0
  144. package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
  145. package/dist/chunks/tabs-f5cw3tgp.js +4 -0
  146. package/dist/chunks/textfield-wewc8rq2.js +4 -0
  147. package/dist/chunks/toast-1gv0h53h.js +4 -0
  148. package/dist/chunks/toast-host-1yg5ar8d.js +4 -0
  149. package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
  150. package/dist/chunks/tooltip-yypz28gq.js +4 -0
  151. package/dist/chunks/tree-9xa4hm7n.js +4 -0
  152. package/dist/chunks/tsMode-epyfz1hv.js +14 -0
  153. package/dist/chunks/workspace-dz7nxfhv.js +4 -0
  154. package/dist/chunks/workspace-home-xsd7hkjw.js +4 -0
  155. package/dist/chunks/ws-client-bv552sfx.js +4 -0
  156. package/dist/iframe-entry.js +20 -16
  157. package/dist/manifest.json +77 -63
  158. package/dist/studio.js +106 -107
  159. package/dist/workers/ts.worker.js +3 -3
  160. package/package.json +17 -16
  161. package/src/about/about-modal.ts +4 -3
  162. package/src/account/action-flow.ts +45 -38
  163. package/src/account-status.ts +7 -2
  164. package/src/browse/component-examples.ts +272 -0
  165. package/src/browse/library-commands.ts +64 -104
  166. package/src/browse/library-layouts.ts +270 -53
  167. package/src/browse/library-model.ts +194 -134
  168. package/src/browse/library-pane.ts +748 -440
  169. package/src/browse/library-preview.ts +161 -26
  170. package/src/browse/library-source.ts +308 -41
  171. package/src/browse/preview-root.ts +78 -0
  172. package/src/browse/preview-style.ts +155 -0
  173. package/src/canvas/asset-refs.ts +40 -10
  174. package/src/canvas/asset-resolve.ts +19 -23
  175. package/src/canvas/canvas-helpers.ts +7 -6
  176. package/src/canvas/canvas-live-render.ts +260 -77
  177. package/src/canvas/canvas-origin.ts +37 -12
  178. package/src/canvas/canvas-page-context.ts +112 -0
  179. package/src/canvas/canvas-patcher.ts +30 -30
  180. package/src/canvas/canvas-perf.ts +11 -5
  181. package/src/canvas/canvas-render.ts +175 -148
  182. package/src/canvas/canvas-surface.ts +5 -3
  183. package/src/canvas/canvas-utils.ts +147 -61
  184. package/src/canvas/dialog-path.ts +9 -4
  185. package/src/canvas/dialog-state.ts +1 -2
  186. package/src/canvas/diff-marks.ts +9 -16
  187. package/src/canvas/diff-toolbar.ts +8 -7
  188. package/src/canvas/edit-width-drag.ts +4 -1
  189. package/src/canvas/edit-width.ts +1 -3
  190. package/src/canvas/iframe-channel.ts +27 -13
  191. package/src/canvas/iframe-drop.ts +120 -12
  192. package/src/canvas/iframe-editable-root.ts +29 -16
  193. package/src/canvas/iframe-entry.ts +104 -75
  194. package/src/canvas/iframe-eval.ts +73 -49
  195. package/src/canvas/iframe-host.ts +269 -158
  196. package/src/canvas/iframe-inline-edit.ts +49 -30
  197. package/src/canvas/iframe-insert.ts +5 -4
  198. package/src/canvas/iframe-interaction.ts +30 -25
  199. package/src/canvas/iframe-keys.ts +11 -0
  200. package/src/canvas/iframe-overlay.ts +1 -1
  201. package/src/canvas/iframe-patch.ts +25 -21
  202. package/src/canvas/iframe-position.ts +12 -6
  203. package/src/canvas/iframe-protocol.ts +36 -21
  204. package/src/canvas/iframe-render.ts +84 -35
  205. package/src/canvas/iframe-slash.ts +24 -11
  206. package/src/canvas/iframe-subtree.ts +10 -3
  207. package/src/canvas/npm-modules.ts +22 -0
  208. package/src/canvas/path-mapping.ts +19 -12
  209. package/src/canvas/popover-path.ts +7 -3
  210. package/src/canvas/popover-state.ts +1 -2
  211. package/src/canvas/preview-navigate.ts +16 -0
  212. package/src/canvas/repeater-sources.ts +200 -0
  213. package/src/canvas/serialize-scope.ts +13 -5
  214. package/src/canvas/stage-scrollbar.ts +7 -2
  215. package/src/canvas/surface-registry.ts +27 -3
  216. package/src/collab/collab-commands.ts +7 -2
  217. package/src/collab/collab-session.ts +84 -45
  218. package/src/collab/collab-state.ts +4 -3
  219. package/src/collab/monaco-binding.ts +16 -13
  220. package/src/collab/monaco-cursors.ts +5 -2
  221. package/src/commands/app-commands.ts +16 -6
  222. package/src/commands/budget.ts +13 -11
  223. package/src/commands/command-args.ts +103 -71
  224. package/src/commands/context.ts +55 -28
  225. package/src/commands/defaults.ts +69 -45
  226. package/src/commands/keymap.ts +56 -43
  227. package/src/commands/levels.ts +14 -8
  228. package/src/commands/live-context.ts +9 -7
  229. package/src/commands/reference.ts +2 -1
  230. package/src/commands/registry.ts +22 -11
  231. package/src/commands/run-reported.ts +15 -10
  232. package/src/component-props.ts +46 -30
  233. package/src/content/collection-match.ts +11 -9
  234. package/src/content/collection-pages.ts +412 -0
  235. package/src/content/content-collections.ts +270 -0
  236. package/src/content/draft-state.ts +4 -3
  237. package/src/content/entry-commands.ts +54 -62
  238. package/src/content/entry-editor.ts +137 -32
  239. package/src/content/entry-fields.ts +25 -8
  240. package/src/content/entry-inspector.ts +225 -0
  241. package/src/content/entry-model.ts +38 -15
  242. package/src/content/entry-open.ts +80 -0
  243. package/src/content/entry-summaries.ts +440 -0
  244. package/src/content/file-record-ids.ts +80 -0
  245. package/src/content/file-records.ts +125 -0
  246. package/src/content/page-summaries.ts +129 -0
  247. package/src/content/record-entry.ts +201 -0
  248. package/src/content/writing-banner.ts +177 -0
  249. package/src/create/add-new-commands.ts +185 -0
  250. package/src/create/add-new-flow.ts +1116 -0
  251. package/src/create/add-new.ts +1014 -0
  252. package/src/create/element-name.ts +121 -0
  253. package/src/editor/canvas-context-menu.ts +1 -2
  254. package/src/editor/canvas-slash-bridge.ts +3 -6
  255. package/src/editor/content-slice.ts +16 -14
  256. package/src/editor/context-menu.ts +35 -22
  257. package/src/editor/convert-targets.ts +30 -35
  258. package/src/editor/convert-to-component.ts +78 -48
  259. package/src/editor/convert-to-repeater.ts +34 -22
  260. package/src/editor/editable-tags.ts +17 -2
  261. package/src/editor/file-drop-action.ts +29 -22
  262. package/src/editor/inline-edit-apply.ts +79 -17
  263. package/src/editor/inline-edit.ts +76 -50
  264. package/src/editor/inline-format.ts +59 -56
  265. package/src/editor/inline-link.ts +40 -15
  266. package/src/editor/insert-component.ts +91 -0
  267. package/src/editor/insert-zone-action.ts +14 -5
  268. package/src/editor/merge-tags.ts +58 -19
  269. package/src/editor/repeater-scope.ts +39 -28
  270. package/src/editor/shortcuts.ts +76 -42
  271. package/src/editor/slash-menu.ts +52 -14
  272. package/src/files/asset-versions.ts +4 -4
  273. package/src/files/components.ts +89 -20
  274. package/src/files/elements.ts +5 -6
  275. package/src/files/file-ops.ts +92 -41
  276. package/src/files/files.ts +248 -239
  277. package/src/files/fs-events.ts +18 -7
  278. package/src/files/media-meta.ts +97 -2
  279. package/src/files/media-paths.ts +3 -0
  280. package/src/files/media-types.ts +55 -0
  281. package/src/files/media-upload.ts +209 -52
  282. package/src/files/new-file-name.ts +156 -0
  283. package/src/files/serialize-document.ts +15 -5
  284. package/src/format/constraints.ts +1 -1
  285. package/src/format/convert-file.ts +27 -13
  286. package/src/format/format-choices.ts +2 -1
  287. package/src/format/format-host.ts +91 -50
  288. package/src/github/github-auth-status.ts +27 -3
  289. package/src/github/github-auth.ts +21 -11
  290. package/src/github/github-publish.ts +28 -23
  291. package/src/grid/cell-editors.ts +46 -31
  292. package/src/grid/cell-popovers.ts +5 -3
  293. package/src/grid/edit-buffer.ts +10 -9
  294. package/src/grid/grid-controller.ts +25 -23
  295. package/src/grid/grid-layout.ts +21 -5
  296. package/src/grid/grid-open.ts +3 -33
  297. package/src/grid/grid-panel.ts +65 -6
  298. package/src/grid/grid-reveal.ts +34 -0
  299. package/src/grid/grid-source.ts +9 -31
  300. package/src/grid/grid-view.ts +45 -23
  301. package/src/grid/redirects-grid.ts +14 -5
  302. package/src/grid/redirects.ts +16 -14
  303. package/src/grid/schema-columns.ts +25 -19
  304. package/src/grid/sources/connector-source.ts +47 -20
  305. package/src/grid/sources/content-source.ts +100 -31
  306. package/src/grid/sources/csv-file-source.ts +2 -2
  307. package/src/grid/tabulator-tables.d.ts +61 -34
  308. package/src/hosting/document.ts +2 -2
  309. package/src/hosting/stage.ts +7 -7
  310. package/src/i18n/i18n-commands.ts +3 -3
  311. package/src/media/media-commands.ts +181 -0
  312. package/src/media/media-library-model.ts +232 -0
  313. package/src/media/media-library.ts +1283 -0
  314. package/src/media/media-pane.ts +51 -20
  315. package/src/new-project/add-repo-modal.ts +20 -19
  316. package/src/new-project/import-tab.ts +10 -14
  317. package/src/new-project/location-fields.ts +2 -1
  318. package/src/new-project/new-project-modal.ts +12 -9
  319. package/src/packages/jxsuite-update.ts +4 -3
  320. package/src/packages/pull-package-sync.ts +26 -25
  321. package/src/page-params.ts +97 -68
  322. package/src/panels/activity-panel.ts +38 -14
  323. package/src/panels/ai-chat/attached-context.ts +13 -7
  324. package/src/panels/ai-chat/chat-markdown.ts +8 -8
  325. package/src/panels/ai-chat/chat-view.ts +80 -73
  326. package/src/panels/ai-chat/composer.ts +30 -33
  327. package/src/panels/ai-chat/sessions-view.ts +1 -2
  328. package/src/panels/ai-panel.ts +23 -20
  329. package/src/panels/block-action-bar.ts +57 -46
  330. package/src/panels/bottom-dock.ts +5 -3
  331. package/src/panels/canvas-dnd-bridge.ts +36 -26
  332. package/src/panels/chat-panel.ts +6 -6
  333. package/src/panels/collections-panel.ts +306 -0
  334. package/src/panels/component-preview.ts +35 -13
  335. package/src/panels/data-explorer.ts +63 -26
  336. package/src/panels/data-grid.ts +18 -11
  337. package/src/panels/dnd.ts +115 -138
  338. package/src/panels/editors.ts +52 -21
  339. package/src/panels/elements-panel.ts +19 -5
  340. package/src/panels/empty-state.ts +2 -2
  341. package/src/panels/events-panel.ts +84 -69
  342. package/src/panels/formula-workspace.ts +78 -54
  343. package/src/panels/frontmatter-fields.ts +33 -28
  344. package/src/panels/git-diff-open.ts +10 -6
  345. package/src/panels/head-panel.ts +488 -202
  346. package/src/panels/i18n-panel.ts +20 -12
  347. package/src/panels/imports-panel.ts +25 -47
  348. package/src/panels/jump-bar.ts +75 -31
  349. package/src/panels/layers-panel.ts +130 -101
  350. package/src/panels/left-panel.ts +25 -11
  351. package/src/panels/navigator-panels.ts +23 -11
  352. package/src/panels/pane-context.ts +140 -49
  353. package/src/panels/pane-grid.ts +55 -26
  354. package/src/panels/panel-registry.ts +36 -46
  355. package/src/panels/properties-panel.ts +182 -124
  356. package/src/panels/quick-search.ts +53 -31
  357. package/src/panels/right-panel.ts +201 -45
  358. package/src/panels/seo-modal.ts +54 -125
  359. package/src/panels/settings-menu.ts +63 -61
  360. package/src/panels/settings-pane.ts +268 -162
  361. package/src/panels/signals-panel.ts +156 -135
  362. package/src/panels/site-model.ts +367 -0
  363. package/src/panels/site-panel.ts +638 -0
  364. package/src/panels/statement-editor.ts +230 -140
  365. package/src/panels/style-panel.ts +253 -206
  366. package/src/panels/style-utils.ts +114 -51
  367. package/src/panels/stylebook-doc.ts +195 -60
  368. package/src/panels/stylebook-layers-panel.ts +48 -89
  369. package/src/panels/stylebook-panel.ts +60 -27
  370. package/src/panels/styles-panel.ts +327 -0
  371. package/src/panels/tab-drop.ts +27 -11
  372. package/src/panels/tab-strip.ts +143 -49
  373. package/src/platform-errors.ts +57 -43
  374. package/src/platform.ts +59 -31
  375. package/src/platforms/cloud.ts +373 -176
  376. package/src/platforms/default-platform.ts +14 -8
  377. package/src/platforms/devserver.ts +180 -142
  378. package/src/platforms/read-batcher.ts +16 -8
  379. package/src/project-list.ts +2 -1
  380. package/src/publish/deploy-checklist.ts +20 -9
  381. package/src/publish/pages-service.ts +66 -27
  382. package/src/publish/publish-changes.ts +491 -0
  383. package/src/publish/publish-commands.ts +88 -22
  384. package/src/publish/publish-ids.ts +49 -0
  385. package/src/publish/publish-panel.ts +10 -6
  386. package/src/publish/publish-quick.ts +148 -0
  387. package/src/publish/publish-workspace.ts +926 -0
  388. package/src/publish/source-control.ts +907 -0
  389. package/src/recent-projects.ts +15 -8
  390. package/src/resize-edges.ts +26 -36
  391. package/src/services/a11y-report.ts +26 -19
  392. package/src/services/agent-seed.ts +23 -11
  393. package/src/services/ai-ask.ts +9 -12
  394. package/src/services/ai-command-tools.ts +68 -62
  395. package/src/services/ai-import-tools.ts +80 -67
  396. package/src/services/ai-models.ts +17 -13
  397. package/src/services/ai-project-tools.ts +68 -32
  398. package/src/services/ai-session-store.ts +19 -10
  399. package/src/services/ai-system-prompt.ts +46 -20
  400. package/src/services/ai-tools.ts +71 -27
  401. package/src/services/ai-write-report.ts +20 -12
  402. package/src/services/ai-writes.ts +4 -4
  403. package/src/services/automation.ts +74 -51
  404. package/src/services/cem-export.ts +149 -58
  405. package/src/services/cf-settings.ts +4 -4
  406. package/src/services/clock.ts +6 -1
  407. package/src/services/code-services.ts +37 -31
  408. package/src/services/connection.ts +2 -2
  409. package/src/services/context-manager.ts +14 -10
  410. package/src/services/context-resolver.ts +20 -8
  411. package/src/services/data-service.ts +19 -15
  412. package/src/services/directory-picker.ts +20 -14
  413. package/src/services/document-assistant.ts +39 -19
  414. package/src/services/gated-registry.ts +10 -6
  415. package/src/services/harness/chat-reducer.ts +23 -1
  416. package/src/services/import-client.ts +91 -38
  417. package/src/services/import-seed.ts +8 -2
  418. package/src/services/jx-validate.ts +28 -31
  419. package/src/services/live-preview.ts +0 -0
  420. package/src/services/live-surfaces.ts +6 -3
  421. package/src/services/model-uri.ts +10 -2
  422. package/src/services/module-preloads.ts +12 -8
  423. package/src/services/monaco-buffer.ts +43 -24
  424. package/src/services/monaco-lazy.ts +7 -8
  425. package/src/services/monaco-setup.ts +23 -16
  426. package/src/services/notify.ts +44 -17
  427. package/src/services/popover-report.ts +25 -10
  428. package/src/services/preview-eval.ts +20 -8
  429. package/src/services/profile.ts +13 -6
  430. package/src/services/project-path.ts +13 -10
  431. package/src/services/references.ts +0 -0
  432. package/src/services/render-critic.ts +29 -9
  433. package/src/services/settings/definitions.ts +25 -14
  434. package/src/services/settings/kernel.ts +13 -4
  435. package/src/services/settings/write-queue.ts +9 -9
  436. package/src/services/token-lint.ts +12 -10
  437. package/src/services/tool-executor.ts +17 -5
  438. package/src/services/tool-outcomes.ts +44 -24
  439. package/src/services/trusted-types.ts +24 -7
  440. package/src/settings/contexts-section.ts +11 -8
  441. package/src/settings/contributed-section.ts +128 -70
  442. package/src/settings/css-vars-editor.ts +119 -32
  443. package/src/settings/defs-editor.ts +38 -35
  444. package/src/settings/developer-panels.ts +43 -0
  445. package/src/settings/extension-rows.ts +16 -8
  446. package/src/settings/extension-sections.ts +42 -14
  447. package/src/settings/extensions-section.ts +4 -1
  448. package/src/settings/general-settings.ts +101 -28
  449. package/src/settings/locales-section.ts +20 -12
  450. package/src/settings/preferences-dialog.ts +17 -7
  451. package/src/settings/preferences-keymap.ts +7 -5
  452. package/src/settings/preferences-sections.ts +11 -5
  453. package/src/settings/project-sections.ts +28 -11
  454. package/src/settings/schema-field-ui.ts +12 -1
  455. package/src/settings/section-registry.ts +116 -11
  456. package/src/settings/settings-dialog.ts +192 -0
  457. package/src/settings/settings-document.ts +186 -166
  458. package/src/shell/tree.ts +6 -5
  459. package/src/shell.ts +536 -477
  460. package/src/site-context.ts +101 -32
  461. package/src/state.ts +68 -57
  462. package/src/store.ts +54 -34
  463. package/src/studio.ts +219 -116
  464. package/src/style/live-preview.ts +1 -1
  465. package/src/style/project-styles.ts +40 -7
  466. package/src/style/stylebook-specimens.ts +89 -0
  467. package/src/style/stylebook-target.ts +26 -0
  468. package/src/style/tag-inheritance.ts +105 -0
  469. package/src/style/token-ref.ts +5 -4
  470. package/src/style/variables-focus.ts +61 -0
  471. package/src/style/variables-view.ts +235 -0
  472. package/src/surfaces/about.ts +18 -19
  473. package/src/surfaces/add-new.json +1482 -0
  474. package/src/surfaces/add-new.ts +325 -0
  475. package/src/surfaces/add-repo.ts +17 -19
  476. package/src/surfaces/ai-chat.ts +33 -38
  477. package/src/surfaces/ai-credentials-form.ts +6 -16
  478. package/src/surfaces/ai-managed-connect.ts +3 -4
  479. package/src/surfaces/ai-model-picker.ts +3 -5
  480. package/src/surfaces/block-action-bar.ts +22 -11
  481. package/src/surfaces/boot-failure.json +4 -3
  482. package/src/surfaces/boot-failure.ts +4 -5
  483. package/src/surfaces/bottom-dock.json +1 -1
  484. package/src/surfaces/bottom-dock.ts +9 -18
  485. package/src/surfaces/canvas-stage.json +30 -19
  486. package/src/surfaces/canvas-stage.ts +17 -16
  487. package/src/surfaces/cf-account-picker.ts +17 -18
  488. package/src/surfaces/collections-panel.json +615 -0
  489. package/src/surfaces/collections-panel.ts +168 -0
  490. package/src/surfaces/commandbar.json +241 -96
  491. package/src/surfaces/commandbar.ts +145 -105
  492. package/src/surfaces/convert-repeater.ts +17 -19
  493. package/src/surfaces/data-actions.ts +9 -7
  494. package/src/surfaces/dialog.ts +26 -28
  495. package/src/surfaces/diff-toolbar.ts +9 -7
  496. package/src/surfaces/empty-state.json +1 -1
  497. package/src/surfaces/empty-state.ts +7 -10
  498. package/src/surfaces/entry-editor.json +136 -0
  499. package/src/surfaces/entry-editor.ts +35 -11
  500. package/src/surfaces/entry-inspector.json +371 -0
  501. package/src/surfaces/entry-inspector.ts +143 -0
  502. package/src/surfaces/expression-editor.ts +11 -25
  503. package/src/surfaces/files-panel.ts +27 -14
  504. package/src/surfaces/formula-palette.ts +4 -5
  505. package/src/surfaces/github-auth.ts +16 -20
  506. package/src/surfaces/github-publish.ts +17 -22
  507. package/src/surfaces/grid-cell.ts +30 -31
  508. package/src/surfaces/grid-open.ts +10 -14
  509. package/src/surfaces/grid-panel.ts +13 -9
  510. package/src/surfaces/grid-replace.ts +13 -13
  511. package/src/surfaces/grid-views.ts +15 -18
  512. package/src/surfaces/inspector-dock.json +162 -14
  513. package/src/surfaces/inspector-dock.ts +59 -31
  514. package/src/surfaces/jump-bar.ts +5 -6
  515. package/src/surfaces/jxsuite-update.ts +16 -22
  516. package/src/surfaces/library-pane.json +670 -437
  517. package/src/surfaces/library-pane.ts +111 -77
  518. package/src/surfaces/logic-panel.ts +17 -30
  519. package/src/surfaces/logic-workspace.ts +13 -15
  520. package/src/surfaces/media-browser.json +62 -6
  521. package/src/surfaces/media-browser.ts +26 -11
  522. package/src/surfaces/media-field.json +1 -1
  523. package/src/surfaces/media-field.ts +4 -5
  524. package/src/surfaces/media-library.json +1586 -0
  525. package/src/surfaces/media-library.ts +282 -0
  526. package/src/surfaces/media-pane.ts +8 -7
  527. package/src/surfaces/media-pick-dialog.json +71 -0
  528. package/src/surfaces/media-pick-dialog.ts +132 -0
  529. package/src/surfaces/menu.ts +47 -23
  530. package/src/surfaces/navigator-dock.ts +11 -12
  531. package/src/surfaces/new-project.ts +27 -26
  532. package/src/surfaces/pane-context.json +144 -77
  533. package/src/surfaces/pane-context.ts +44 -25
  534. package/src/surfaces/pane-grid.ts +15 -10
  535. package/src/surfaces/panel-activity.ts +5 -6
  536. package/src/surfaces/panel-data.ts +3 -4
  537. package/src/surfaces/panel-deploy-checklist.json +12 -6
  538. package/src/surfaces/panel-deploy-checklist.ts +8 -7
  539. package/src/surfaces/panel-elements.ts +5 -7
  540. package/src/surfaces/panel-i18n.ts +5 -7
  541. package/src/surfaces/panel-imports.ts +6 -13
  542. package/src/surfaces/panel-outline.ts +25 -19
  543. package/src/surfaces/panel-page.json +72 -2
  544. package/src/surfaces/panel-page.ts +49 -25
  545. package/src/surfaces/panel-problems.ts +5 -7
  546. package/src/surfaces/panel-signals.json +1 -1
  547. package/src/surfaces/panel-signals.ts +25 -39
  548. package/src/surfaces/panel-stylebook-layers.json +71 -204
  549. package/src/surfaces/panel-stylebook-layers.ts +5 -29
  550. package/src/surfaces/preferences.json +120 -48
  551. package/src/surfaces/preferences.ts +29 -11
  552. package/src/surfaces/progress-modal.ts +15 -9
  553. package/src/surfaces/properties-panel.json +1 -1
  554. package/src/surfaces/properties-panel.ts +20 -42
  555. package/src/surfaces/publish-quick.json +428 -0
  556. package/src/surfaces/publish-quick.ts +165 -0
  557. package/src/surfaces/publish-workspace.json +2892 -0
  558. package/src/surfaces/publish-workspace.ts +391 -0
  559. package/src/surfaces/publish.ts +18 -18
  560. package/src/surfaces/push-plan.ts +7 -8
  561. package/src/surfaces/rail.json +1 -159
  562. package/src/surfaces/rail.ts +22 -79
  563. package/src/surfaces/reference-field.ts +11 -15
  564. package/src/surfaces/schema-builder.ts +16 -22
  565. package/src/surfaces/schema-form.json +10 -2
  566. package/src/surfaces/schema-form.ts +17 -25
  567. package/src/surfaces/secret-field.ts +9 -6
  568. package/src/surfaces/seo.json +1 -1
  569. package/src/surfaces/seo.ts +21 -15
  570. package/src/surfaces/settings-contexts.ts +9 -7
  571. package/src/surfaces/settings-contributed.json +5 -5
  572. package/src/surfaces/settings-contributed.ts +32 -12
  573. package/src/surfaces/settings-css-vars.json +44 -36
  574. package/src/surfaces/settings-css-vars.ts +82 -16
  575. package/src/surfaces/settings-defs.json +2 -2
  576. package/src/surfaces/settings-defs.ts +17 -21
  577. package/src/surfaces/settings-deploy.json +2 -15
  578. package/src/surfaces/settings-deploy.ts +9 -16
  579. package/src/surfaces/settings-dialog.json +51 -0
  580. package/src/surfaces/settings-dialog.ts +169 -0
  581. package/src/surfaces/settings-extensions.ts +5 -6
  582. package/src/surfaces/settings-head.ts +33 -39
  583. package/src/surfaces/settings-locales.ts +8 -20
  584. package/src/surfaces/settings-overview.json +3 -3
  585. package/src/surfaces/settings-overview.ts +14 -8
  586. package/src/surfaces/settings-packages.ts +8 -7
  587. package/src/surfaces/settings-pane.json +269 -46
  588. package/src/surfaces/settings-pane.ts +88 -36
  589. package/src/surfaces/settings-rawjson.ts +5 -6
  590. package/src/surfaces/shell.json +2 -1
  591. package/src/surfaces/shell.ts +1 -2
  592. package/src/surfaces/site-panel.json +1029 -0
  593. package/src/surfaces/site-panel.ts +233 -0
  594. package/src/surfaces/slash-menu.json +63 -21
  595. package/src/surfaces/slash-menu.ts +42 -9
  596. package/src/surfaces/statements.ts +13 -18
  597. package/src/surfaces/statusbar.ts +56 -29
  598. package/src/surfaces/style-panel.ts +18 -31
  599. package/src/surfaces/stylebook-chrome.ts +3 -5
  600. package/src/surfaces/styles-panel.json +735 -0
  601. package/src/surfaces/styles-panel.ts +195 -0
  602. package/src/surfaces/styles-variables.json +149 -0
  603. package/src/surfaces/styles-variables.ts +145 -0
  604. package/src/surfaces/tab-strip.json +4 -4
  605. package/src/surfaces/tab-strip.ts +14 -13
  606. package/src/surfaces/target-line.ts +6 -7
  607. package/src/surfaces/welcome.ts +6 -8
  608. package/src/surfaces/writing-banner.json +94 -0
  609. package/src/surfaces/writing-banner.ts +80 -0
  610. package/src/tabs/bare-repeaters.ts +101 -0
  611. package/src/tabs/patch-ops.ts +4 -3
  612. package/src/tabs/project-config.ts +32 -21
  613. package/src/tabs/selection.ts +36 -8
  614. package/src/tabs/tab.ts +99 -48
  615. package/src/tabs/transact.ts +98 -53
  616. package/src/types.ts +53 -43
  617. package/src/ui/ai-credentials-form.ts +10 -13
  618. package/src/ui/ai-model-picker.ts +3 -3
  619. package/src/ui/cf-account-picker.ts +7 -9
  620. package/src/ui/color-selector.ts +9 -5
  621. package/src/ui/dynamic-slot.ts +7 -8
  622. package/src/ui/expression-editor.ts +112 -105
  623. package/src/ui/form-controls.ts +104 -56
  624. package/src/ui/formula-catalog.ts +239 -230
  625. package/src/ui/formula-chips.ts +33 -18
  626. package/src/ui/layers.ts +57 -31
  627. package/src/ui/media-picker.ts +300 -47
  628. package/src/ui/popover-surface.ts +20 -12
  629. package/src/ui/progress-modal.ts +13 -8
  630. package/src/ui/regions.ts +14 -12
  631. package/src/ui/schema-form.ts +372 -97
  632. package/src/ui/surface.ts +71 -8
  633. package/src/ui/timing.ts +9 -0
  634. package/src/ui/value-source.ts +44 -31
  635. package/src/ui/virtual-window.ts +29 -3
  636. package/src/utils/base64.ts +6 -4
  637. package/src/utils/edit-display.ts +366 -111
  638. package/src/utils/element-selectors.ts +3 -2
  639. package/src/utils/google-fonts.ts +15 -14
  640. package/src/utils/inherited-style.ts +18 -20
  641. package/src/utils/link-target.ts +1 -1
  642. package/src/utils/local-day.ts +18 -0
  643. package/src/utils/preview-format.ts +25 -3
  644. package/src/utils/strip-events.ts +49 -22
  645. package/src/utils/studio-utils.ts +29 -14
  646. package/src/view.ts +2 -3
  647. package/src/workspace/pane-derive.ts +14 -16
  648. package/src/workspace/session.ts +81 -50
  649. package/src/workspace/tab-workspace.ts +137 -0
  650. package/src/workspace/workspace-back.ts +189 -0
  651. package/src/workspace/workspace-home.ts +133 -0
  652. package/src/workspace/workspace-ids.ts +129 -0
  653. package/src/workspace/workspace-switch.ts +372 -0
  654. package/src/workspace/workspace.ts +165 -47
  655. package/styles/shell-frame.css +30 -7
  656. package/styles/shell-frame.json +15 -3
  657. package/dist/chunks/2020-va2wwra4.js +0 -4
  658. package/dist/chunks/adapter-f93pafd7.js +0 -4
  659. package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
  660. package/dist/chunks/cf-settings-125tdm0w.js +0 -4
  661. package/dist/chunks/color-area-jqhna8zy.js +0 -4
  662. package/dist/chunks/color-field-embq5ctg.js +0 -4
  663. package/dist/chunks/color-fpezvnkt.js +0 -4
  664. package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
  665. package/dist/chunks/combobox-773hdzyj.js +0 -4
  666. package/dist/chunks/components-ax2f1fnn.js +0 -4
  667. package/dist/chunks/content-source-108aqtk1.js +0 -4
  668. package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
  669. package/dist/chunks/dialog-mtm9fq5t.js +0 -4
  670. package/dist/chunks/editor-pfgdmkb0.js +0 -4
  671. package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
  672. package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
  673. package/dist/chunks/file-ops-meej5mqf.js +0 -4
  674. package/dist/chunks/files-44vp8a2s.js +0 -4
  675. package/dist/chunks/format-host-7q1petb9.js +0 -4
  676. package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
  677. package/dist/chunks/git-panel-zngbymvd.js +0 -4
  678. package/dist/chunks/grid-view-sx9vynsp.js +0 -51
  679. package/dist/chunks/icons-p44xhjf0.js +0 -4
  680. package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
  681. package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
  682. package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
  683. package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
  684. package/dist/chunks/index-wkyfjeqz.js +0 -4
  685. package/dist/chunks/jsonMode-s8kt9dsj.js +0 -13
  686. package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
  687. package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
  688. package/dist/chunks/layers-xd92fg8d.js +0 -4
  689. package/dist/chunks/listbox-s8fkmnq8.js +0 -4
  690. package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
  691. package/dist/chunks/media-picker-0svzkdyb.js +0 -4
  692. package/dist/chunks/menu-37d07z9m.js +0 -4
  693. package/dist/chunks/menu-5c55ea3d.js +0 -4
  694. package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
  695. package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
  696. package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
  697. package/dist/chunks/notify-0xgtn8q1.js +0 -4
  698. package/dist/chunks/number-field-gw7sq8rn.js +0 -4
  699. package/dist/chunks/parse-897fvqah.js +0 -4
  700. package/dist/chunks/platform-v1qctbe6.js +0 -4
  701. package/dist/chunks/popover-8htra4er.js +0 -4
  702. package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
  703. package/dist/chunks/quick-search-a54e6t5n.js +0 -4
  704. package/dist/chunks/references-gmqp82fs.js +0 -4
  705. package/dist/chunks/right-panel-v7t9awbk.js +0 -4
  706. package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
  707. package/dist/chunks/select-n3v7gwas.js +0 -4
  708. package/dist/chunks/split-pff8f3ze.js +0 -4
  709. package/dist/chunks/studio-0bhx5hz6.js +0 -5
  710. package/dist/chunks/studio-0k1ddnyy.js +0 -6
  711. package/dist/chunks/studio-1b04pd0j.js +0 -64
  712. package/dist/chunks/studio-4dwbj6gb.js +0 -5
  713. package/dist/chunks/studio-4tanh828.js +0 -5
  714. package/dist/chunks/studio-55h4mstj.js +0 -4
  715. package/dist/chunks/studio-5tnvjkz4.js +0 -5
  716. package/dist/chunks/studio-60dqgb0c.js +0 -5
  717. package/dist/chunks/studio-61dp09qg.js +0 -9
  718. package/dist/chunks/studio-63epcrj2.js +0 -5
  719. package/dist/chunks/studio-74k29dy9.js +0 -5
  720. package/dist/chunks/studio-7vg6jcd3.js +0 -5
  721. package/dist/chunks/studio-7zx31knw.js +0 -9
  722. package/dist/chunks/studio-8bxk97km.js +0 -5
  723. package/dist/chunks/studio-933e30n4.js +0 -5
  724. package/dist/chunks/studio-98wnwhbg.js +0 -5
  725. package/dist/chunks/studio-9mccjwjh.js +0 -14
  726. package/dist/chunks/studio-a2ke1e4t.js +0 -5
  727. package/dist/chunks/studio-e3a2a6v3.js +0 -4
  728. package/dist/chunks/studio-e81q1vb9.js +0 -5
  729. package/dist/chunks/studio-epgrmqqm.js +0 -5
  730. package/dist/chunks/studio-ery42sqr.js +0 -4
  731. package/dist/chunks/studio-g1shz58g.js +0 -5
  732. package/dist/chunks/studio-gf0fz03c.js +0 -5
  733. package/dist/chunks/studio-gjtpe62q.js +0 -6
  734. package/dist/chunks/studio-gkskhg7m.js +0 -5
  735. package/dist/chunks/studio-gx4dnjzd.js +0 -5
  736. package/dist/chunks/studio-j03zga3y.js +0 -9
  737. package/dist/chunks/studio-jhpxeckz.js +0 -5
  738. package/dist/chunks/studio-k01r7ykp.js +0 -5
  739. package/dist/chunks/studio-kk7h30ne.js +0 -7
  740. package/dist/chunks/studio-kt1zqney.js +0 -5
  741. package/dist/chunks/studio-m3cwhvye.js +0 -5
  742. package/dist/chunks/studio-mcayt6hz.js +0 -5
  743. package/dist/chunks/studio-myjcghv3.js +0 -5
  744. package/dist/chunks/studio-n8bxwc3y.js +0 -4
  745. package/dist/chunks/studio-ngm8gvpb.js +0 -5
  746. package/dist/chunks/studio-nj5a01jy.js +0 -928
  747. package/dist/chunks/studio-pcgz8heb.js +0 -5
  748. package/dist/chunks/studio-qcsq0t15.js +0 -5
  749. package/dist/chunks/studio-qkstvve9.js +0 -5
  750. package/dist/chunks/studio-qv1pwd3c.js +0 -5
  751. package/dist/chunks/studio-rc6dvxjb.js +0 -7
  752. package/dist/chunks/studio-s8dmmz66.js +0 -5
  753. package/dist/chunks/studio-sp5xzbj4.js +0 -6
  754. package/dist/chunks/studio-szsjbj0g.js +0 -5
  755. package/dist/chunks/studio-t1xzawhr.js +0 -16
  756. package/dist/chunks/studio-tdcprbqb.js +0 -5
  757. package/dist/chunks/studio-vrmcjf9g.js +0 -7
  758. package/dist/chunks/studio-vyc0b4he.js +0 -10
  759. package/dist/chunks/studio-w0cgf6jg.js +0 -5
  760. package/dist/chunks/studio-w3hskzqk.js +0 -5
  761. package/dist/chunks/studio-xgrgcdyh.js +0 -9
  762. package/dist/chunks/studio-xz2yxfcb.js +0 -5
  763. package/dist/chunks/studio-y6n42tgs.js +0 -5
  764. package/dist/chunks/studio-yb560vxr.js +0 -5
  765. package/dist/chunks/studio-yn9f8vtx.js +0 -5
  766. package/dist/chunks/studio-yw05w8f0.js +0 -7
  767. package/dist/chunks/studio-z16sgavc.js +0 -5
  768. package/dist/chunks/studio-zey7zsdw.js +0 -12
  769. package/dist/chunks/studio-zyqn40w4.js +0 -5
  770. package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
  771. package/dist/chunks/tabs-jwthg40w.js +0 -4
  772. package/dist/chunks/textfield-spy3hc77.js +0 -4
  773. package/dist/chunks/toast-4d35zd64.js +0 -4
  774. package/dist/chunks/toast-host-8sjmfed3.js +0 -4
  775. package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
  776. package/dist/chunks/tree-h19v1jfz.js +0 -4
  777. package/dist/chunks/tsMode-2frah6h1.js +0 -14
  778. package/dist/chunks/workspace-zt81g1ms.js +0 -4
  779. package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
  780. package/src/panels/frontmatter-panel.ts +0 -701
  781. package/src/panels/git-panel.ts +0 -1120
  782. package/src/surfaces/doc-header.json +0 -776
  783. package/src/surfaces/doc-header.ts +0 -231
  784. package/src/surfaces/git-panel.json +0 -1880
  785. package/src/surfaces/git-panel.ts +0 -272
@@ -16,7 +16,8 @@ import type { CollabNegotiation } from "@jxsuite/collab/negotiate";
16
16
  // Static, and free to be: `reconnect.ts` imports nothing, so no Yjs reaches the initial bundle.
17
17
  import { createReconnectScheduler } from "@jxsuite/collab/reconnect";
18
18
  import type { WsCollabConnection } from "@jxsuite/collab/client";
19
- import type { ProjectConfig } from "@jxsuite/schema/types";
19
+ import { isBoolean, isJsonObject, isNonNullObject, isString } from "@jxsuite/schema/guards";
20
+ import type { JsonObject, JsonValue, JxMutableNode, ProjectConfig } from "@jxsuite/schema/types";
20
21
  import { componentMetaFrom } from "@jxsuite/schema/component-meta";
21
22
  import { streamImport } from "../services/import-client";
22
23
  import type {
@@ -55,7 +56,9 @@ import type {
55
56
  import { problemDetail, problemSlug } from "@jxsuite/protocol";
56
57
  import type { ReadFilesRequest, ReadFilesResult, UploadResult } from "@jxsuite/protocol";
57
58
  import { reportActionRequired } from "../account/action-required";
59
+ import type { ActionRequiredReport } from "../account/action-required";
58
60
  import { offeredActions, retryHint } from "../platform-errors";
61
+ import type { PlatformErrorInfo } from "../platform-errors";
59
62
  import { createReadBatcher } from "./read-batcher";
60
63
  import { normalizeProjectDir } from "../utils/project-dir";
61
64
  import type { BatchAnswer } from "./read-batcher";
@@ -79,7 +82,7 @@ interface ProjectInfoWire {
79
82
  name: string;
80
83
  defaultBranch: string;
81
84
  permission: "admin" | "write" | "read" | "none";
82
- projectConfig: Record<string, unknown> | null;
85
+ projectConfig: ProjectConfig | null;
83
86
  }
84
87
 
85
88
  /** One row of the platform's project catalogue (`GET /api/v1/projects`). */
@@ -91,6 +94,64 @@ interface ProjectListWire {
91
94
  permission: string;
92
95
  }
93
96
 
97
+ /**
98
+ * True when a `POST /files/read` body is the route answering: a JSON object whose `files` is an
99
+ * array. Only that much is checked here, because the batcher checks every row, and `omitted`,
100
+ * before it trusts any of them (read-batcher.ts `settleAnswer`).
101
+ */
102
+ function isReadFilesAnswer(body: JsonValue): body is JsonObject & ReadFilesResult {
103
+ return isJsonObject(body) && Array.isArray(body["files"]);
104
+ }
105
+
106
+ /** The options object {@link StudioPlatform.formatAction} hands through to `POST /format`. */
107
+ type FormatActionPayload = Parameters<NonNullable<StudioPlatform["formatAction"]>>[0];
108
+
109
+ /**
110
+ * A Cloudflare proxy reply (`/api/v1/cf/proxy` here, `/__studio/cf/proxy` on the dev server):
111
+ * Cloudflare's v4 envelope, or the proxy's own `error`.
112
+ */
113
+ export interface CfProxyEnvelope extends JsonObject {
114
+ success?: boolean;
115
+ result?: JsonValue;
116
+ errors?: { message: string }[];
117
+ error?: string;
118
+ }
119
+
120
+ /** Where a session file sits in its project, as `resolveSiteContext` reports it. */
121
+ interface SiteContext {
122
+ sitePath: string | null;
123
+ projectConfig?: ProjectConfig;
124
+ fileRelPath?: string;
125
+ }
126
+
127
+ /** The signed-in GitHub user, as `getUser` reports them. */
128
+ interface SignedInUser {
129
+ login: string;
130
+ name?: string;
131
+ avatarUrl?: string;
132
+ }
133
+
134
+ /** Body of `POST /api/v1/projects/import`: the repository, and the project folder when not its root. */
135
+ interface ImportProjectRequest {
136
+ owner: string;
137
+ name: string;
138
+ dir?: string;
139
+ }
140
+
141
+ /**
142
+ * A manifest's `dependencies` or `devDependencies` block, `{}` when absent. The object itself, not
143
+ * a copy, so `addPackage` can write into it.
144
+ */
145
+ function dependencyBlock(
146
+ pkg: JsonObject,
147
+ key: "dependencies" | "devDependencies",
148
+ ): Record<string, string> {
149
+ /* SAFETY: npm's package.json format defines both blocks as an object of package name → version
150
+ range string, and every member here that writes one (`addPackage`, `removePackage`) keeps it
151
+ that way. */
152
+ return (pkg[key] ?? {}) as Record<string, string>;
153
+ }
154
+
94
155
  interface SessionEventWire {
95
156
  kind: "fs" | "git";
96
157
  events?: FsEvent[];
@@ -110,9 +171,24 @@ interface ErrorBody {
110
171
  code?: string;
111
172
  }
112
173
 
174
+ /** Parse a fetch Response body as JSON, asserting the expected shape at the boundary. */
175
+ async function readJson<T>(res: Response): Promise<T> {
176
+ /* SAFETY: every response read here comes from a Studio Backend Protocol session route or one of
177
+ the platform's own `/api/v1/*` routes, whose bodies have the shapes @jxsuite/protocol, ../types
178
+ and the wire interfaces in this file describe; each caller names the type of the route it
179
+ called, and a JSON parse always yields a JsonValue. */
180
+ return (await res.json()) as T;
181
+ }
182
+
183
+ /** Parse JSON text a session read returned; JSON.parse only ever produces JSON values. */
184
+ function parseJson(text: string): JsonValue {
185
+ // SAFETY: JSON.parse returns exactly the JSON value the text encodes, or throws.
186
+ return JSON.parse(text) as JsonValue;
187
+ }
188
+
113
189
  async function errorMessage(res: Response, fallback: string): Promise<string> {
114
190
  try {
115
- return problemDetail(await res.json()) ?? fallback;
191
+ return problemDetail(await readJson<JsonValue>(res)) ?? fallback;
116
192
  } catch {
117
193
  return fallback;
118
194
  }
@@ -124,9 +200,9 @@ async function errorMessage(res: Response, fallback: string): Promise<string> {
124
200
  * says the same. Any other 403 (an expired grant, a revoked share) is not that verdict.
125
201
  */
126
202
  async function isReadOnlyRefusal(res: Response): Promise<boolean> {
127
- let body: (ErrorBody & { type?: unknown }) | null;
203
+ let body: StructuredBody | null;
128
204
  try {
129
- body = (await res.json()) as (ErrorBody & { type?: unknown }) | null;
205
+ body = await readJson<StructuredBody | null>(res);
130
206
  } catch {
131
207
  return false;
132
208
  }
@@ -136,16 +212,22 @@ async function isReadOnlyRefusal(res: Response): Promise<boolean> {
136
212
 
137
213
  /** A failure body's machine-readable members, each one optional and none of them trusted. */
138
214
  interface StructuredBody extends ErrorBody {
139
- type?: unknown;
140
- installUrl?: unknown;
141
- actions?: unknown;
142
- heading?: unknown;
143
- retry?: unknown;
215
+ type?: JsonValue;
216
+ installUrl?: JsonValue;
217
+ actions?: JsonValue;
218
+ heading?: JsonValue;
219
+ retry?: JsonValue;
220
+ }
221
+
222
+ /** What {@link platformError} carries on the Error it returns: the HTTP status, plus what it found. */
223
+ interface PlatformErrorDetails extends PlatformErrorInfo {
224
+ status: number;
144
225
  }
145
226
 
146
227
  /** The refusal's heading, when the body carries a usable one. */
147
228
  function headingOf(body: StructuredBody | null): string | undefined {
148
- return typeof body?.heading === "string" && body.heading ? body.heading : undefined;
229
+ const heading = body?.heading;
230
+ return isString(heading) && heading ? heading : undefined;
149
231
  }
150
232
 
151
233
  /**
@@ -161,7 +243,7 @@ function headingOf(body: StructuredBody | null): string | undefined {
161
243
  async function platformError(res: Response, fallback: string): Promise<Error> {
162
244
  let body: StructuredBody | null;
163
245
  try {
164
- body = (await res.json()) as StructuredBody | null;
246
+ body = await readJson<StructuredBody | null>(res);
165
247
  } catch {
166
248
  body = null;
167
249
  }
@@ -169,21 +251,31 @@ async function platformError(res: Response, fallback: string): Promise<Error> {
169
251
  const actions = offeredActions(body?.actions);
170
252
  const heading = headingOf(body);
171
253
  const retry = retryHint(body?.retry);
172
- return Object.assign(new Error(problemDetail(body) ?? fallback), {
173
- status: res.status,
174
- ...(code ? { code } : {}),
175
- ...(typeof body?.installUrl === "string" ? { installUrl: body.installUrl } : {}),
176
- ...(actions.length > 0 ? { actions } : {}),
177
- ...(heading === undefined ? {} : { heading }),
178
- ...(retry === undefined ? {} : { retry }),
179
- });
254
+ const installUrl = body?.installUrl;
255
+ const details: PlatformErrorDetails = { status: res.status };
256
+ if (code) {
257
+ details.code = code;
258
+ }
259
+ if (isString(installUrl)) {
260
+ details.installUrl = installUrl;
261
+ }
262
+ if (actions.length > 0) {
263
+ details.actions = actions;
264
+ }
265
+ if (heading !== undefined) {
266
+ details.heading = heading;
267
+ }
268
+ if (retry !== undefined) {
269
+ details.retry = retry;
270
+ }
271
+ return Object.assign(new Error(problemDetail(body) ?? fallback), details);
180
272
  }
181
273
 
182
274
  async function okJson<T>(res: Response, fallback: string): Promise<T> {
183
275
  if (!res.ok) {
184
276
  throw await platformError(res, fallback);
185
277
  }
186
- return (await res.json()) as T;
278
+ return readJson<T>(res);
187
279
  }
188
280
 
189
281
  /** Whether a failure body is an `action-required` refusal, by problem type or legacy code. */
@@ -201,7 +293,7 @@ function isActionRequiredBody(body: StructuredBody | null): boolean {
201
293
  async function reportRefusal(res: Response): Promise<void> {
202
294
  let body: StructuredBody | null;
203
295
  try {
204
- body = (await res.json()) as StructuredBody | null;
296
+ body = await readJson<StructuredBody | null>(res);
205
297
  } catch {
206
298
  return;
207
299
  }
@@ -215,12 +307,17 @@ async function reportRefusal(res: Response): Promise<void> {
215
307
  const detail = problemDetail(body);
216
308
  const heading = headingOf(body);
217
309
  const retry = retryHint(body?.retry);
218
- reportActionRequired({
219
- actions,
220
- ...(detail === null ? {} : { detail }),
221
- ...(heading === undefined ? {} : { heading }),
222
- ...(retry === undefined ? {} : { retry }),
223
- });
310
+ const report: ActionRequiredReport = { actions };
311
+ if (detail !== null) {
312
+ report.detail = detail;
313
+ }
314
+ if (heading !== undefined) {
315
+ report.heading = heading;
316
+ }
317
+ if (retry !== undefined) {
318
+ report.retry = retry;
319
+ }
320
+ reportActionRequired(report);
224
321
  }
225
322
 
226
323
  /**
@@ -298,6 +395,34 @@ export function projectRootKey(project: CloudProject): string {
298
395
  return `${project.owner}/${project.repo}@${revisionSpec(project)}`;
299
396
  }
300
397
 
398
+ /** `GET /api/v1/cf/connection`: the broker's row, with every diagnostic it may send. */
399
+ interface CfConnectionWire {
400
+ connected: boolean;
401
+ accountId?: string | null;
402
+ accountName?: string | null;
403
+ needsReconnect?: boolean;
404
+ needsAccount?: boolean;
405
+ code?: CfConnection["code"];
406
+ reason?: string;
407
+ hasRefreshToken?: boolean;
408
+ expiresAt?: number;
409
+ }
410
+
411
+ /**
412
+ * A same-origin window relay (`{source, status, reason?}`) that a broker or action window posts
413
+ * back. Only `source` is checked; `status` and `reason` are read as the relay protocol sends them.
414
+ */
415
+ interface WindowRelay {
416
+ source?: string;
417
+ status?: string;
418
+ reason?: string | null;
419
+ }
420
+
421
+ /** True when a `message` event carries a relay from `source` (`"jx-cf"`, `"jx-action"`). */
422
+ function isRelayEvent(event: MessageEvent, source: string): event is MessageEvent<WindowRelay> {
423
+ return isNonNullObject(event.data) && "source" in event.data && event.data.source === source;
424
+ }
425
+
301
426
  /**
302
427
  * Current hosted Cloudflare connection; null when none is brokered yet.
303
428
  *
@@ -312,33 +437,38 @@ async function fetchCfConnection(): Promise<CfConnection | null> {
312
437
  if (!res.ok) {
313
438
  return null;
314
439
  }
315
- const body = (await res.json()) as {
316
- connected: boolean;
317
- accountId?: string | null;
318
- accountName?: string | null;
319
- needsReconnect?: boolean;
320
- needsAccount?: boolean;
321
- code?: CfConnection["code"];
322
- reason?: string;
323
- hasRefreshToken?: boolean;
324
- expiresAt?: number;
325
- };
440
+ const body = await readJson<CfConnectionWire>(res);
326
441
  /* Cloud never emits {connected: false} to the PAL — no brokered row at all is `null`, and a row
327
442
  that cannot be used arrives as connected + needsReconnect. See CfConnection. */
328
443
  if (!body.connected) {
329
444
  return null;
330
445
  }
331
- return {
332
- connected: true,
333
- ...(body.accountId ? { accountId: body.accountId } : {}),
334
- ...(body.accountName ? { accountName: body.accountName } : {}),
335
- ...(body.needsReconnect ? { needsReconnect: true } : {}),
336
- ...(body.needsAccount ? { needsAccount: true } : {}),
337
- ...(body.code ? { code: body.code } : {}),
338
- ...(body.reason ? { reason: body.reason } : {}),
339
- ...(body.hasRefreshToken === undefined ? {} : { hasRefreshToken: body.hasRefreshToken }),
340
- ...(body.expiresAt === undefined ? {} : { expiresAt: body.expiresAt }),
341
- };
446
+ const connection: CfConnection = { connected: true };
447
+ if (body.accountId) {
448
+ connection.accountId = body.accountId;
449
+ }
450
+ if (body.accountName) {
451
+ connection.accountName = body.accountName;
452
+ }
453
+ if (body.needsReconnect) {
454
+ connection.needsReconnect = true;
455
+ }
456
+ if (body.needsAccount) {
457
+ connection.needsAccount = true;
458
+ }
459
+ if (body.code) {
460
+ connection.code = body.code;
461
+ }
462
+ if (body.reason) {
463
+ connection.reason = body.reason;
464
+ }
465
+ if (body.hasRefreshToken !== undefined) {
466
+ connection.hasRefreshToken = body.hasRefreshToken;
467
+ }
468
+ if (body.expiresAt !== undefined) {
469
+ connection.expiresAt = body.expiresAt;
470
+ }
471
+ return connection;
342
472
  }
343
473
 
344
474
  interface CfConnectFlow {
@@ -403,10 +533,10 @@ async function runCfConnect(
403
533
  if (event.origin !== location.origin) {
404
534
  return;
405
535
  }
406
- const data = event.data as { source?: string; status?: string; reason?: string | null };
407
- if (!data || data.source !== "jx-cf") {
536
+ if (!isRelayEvent(event, "jx-cf")) {
408
537
  return;
409
538
  }
539
+ const { data } = event;
410
540
  if (data.status === "error") {
411
541
  fail(data.reason ?? "Cloudflare authorization failed");
412
542
  return;
@@ -467,68 +597,76 @@ async function runCfConnect(
467
597
  interface MeWire {
468
598
  installations?: { id: number; account: string | null; manageUrl?: string }[];
469
599
  appInstallUrl?: string;
470
- entries?: unknown;
471
- notices?: unknown;
600
+ entries?: JsonValue;
601
+ notices?: JsonValue;
472
602
  }
473
603
 
474
604
  /** A wire value as a non-empty string, or undefined. */
475
- function wireText(value: unknown): string | undefined {
476
- return typeof value === "string" && value ? value : undefined;
605
+ function wireText(value: JsonValue | undefined): string | undefined {
606
+ return isString(value) && value ? value : undefined;
477
607
  }
478
608
 
479
609
  /**
480
610
  * The account rows a `/me` body holds, each one checked. A row needs an id, a label and a detail to
481
611
  * be drawn at all; a malformed one is dropped rather than drawn half-empty.
482
612
  */
483
- function accountEntries(value: unknown): AccountEntry[] {
613
+ function accountEntries(value: JsonValue | undefined): AccountEntry[] {
484
614
  if (!Array.isArray(value)) {
485
615
  return [];
486
616
  }
487
- return value.flatMap((raw: Record<string, unknown> | null): AccountEntry[] => {
488
- const id = wireText(raw?.["id"]);
489
- const label = wireText(raw?.["label"]);
490
- const detail = wireText(raw?.["detail"]);
617
+ return value.flatMap((raw): AccountEntry[] => {
618
+ // A row that is not an object has no id, label or detail to draw.
619
+ if (!isJsonObject(raw)) {
620
+ return [];
621
+ }
622
+ const id = wireText(raw["id"]);
623
+ const label = wireText(raw["label"]);
624
+ const detail = wireText(raw["detail"]);
491
625
  if (!id || !label || !detail) {
492
626
  return [];
493
627
  }
494
- const actions = offeredActions(raw?.["actions"]);
495
- return [
496
- {
497
- detail,
498
- id,
499
- label,
500
- ...(typeof raw?.["connected"] === "boolean" ? { connected: raw["connected"] } : {}),
501
- ...(actions.length > 0 ? { actions } : {}),
502
- },
503
- ];
628
+ const actions = offeredActions(raw["actions"]);
629
+ const { connected } = raw;
630
+ const entry: AccountEntry = { detail, id, label };
631
+ if (isBoolean(connected)) {
632
+ entry.connected = connected;
633
+ }
634
+ if (actions.length > 0) {
635
+ entry.actions = actions;
636
+ }
637
+ return [entry];
504
638
  });
505
639
  }
506
640
 
507
641
  /** The notices a `/me` body holds, each one checked, on the same terms as the rows. */
508
- function accountNotices(value: unknown): AccountNotice[] {
642
+ function accountNotices(value: JsonValue | undefined): AccountNotice[] {
509
643
  if (!Array.isArray(value)) {
510
644
  return [];
511
645
  }
512
- return value.flatMap((raw: Record<string, unknown> | null): AccountNotice[] => {
513
- const id = wireText(raw?.["id"]);
514
- const title = wireText(raw?.["title"]);
515
- const message = wireText(raw?.["message"]);
646
+ return value.flatMap((raw): AccountNotice[] => {
647
+ // A notice that is not an object has no id, title or message to show.
648
+ if (!isJsonObject(raw)) {
649
+ return [];
650
+ }
651
+ const id = wireText(raw["id"]);
652
+ const title = wireText(raw["title"]);
653
+ const message = wireText(raw["message"]);
516
654
  if (!id || !title || !message) {
517
655
  return [];
518
656
  }
519
- const actions = offeredActions(raw?.["actions"]);
520
- const level = raw?.["level"];
521
- const display = raw?.["display"];
522
- return [
523
- {
524
- id,
525
- message,
526
- title,
527
- ...(level === "info" || level === "warning" ? { level } : {}),
528
- ...(display === "banner" || display === "toast" ? { display } : {}),
529
- ...(actions.length > 0 ? { actions } : {}),
530
- },
531
- ];
657
+ const actions = offeredActions(raw["actions"]);
658
+ const { display, level } = raw;
659
+ const notice: AccountNotice = { id, message, title };
660
+ if (level === "info" || level === "warning") {
661
+ notice.level = level;
662
+ }
663
+ if (display === "banner" || display === "toast") {
664
+ notice.display = display;
665
+ }
666
+ if (actions.length > 0) {
667
+ notice.actions = actions;
668
+ }
669
+ return [notice];
532
670
  });
533
671
  }
534
672
 
@@ -578,10 +716,10 @@ function awaitAction(popup: Window): Promise<ActionOutcome> {
578
716
  if (event.origin !== location.origin) {
579
717
  return;
580
718
  }
581
- const data = event.data as { source?: string; status?: string; reason?: string | null };
582
- if (!data || data.source !== "jx-action") {
719
+ if (!isRelayEvent(event, "jx-action")) {
583
720
  return;
584
721
  }
722
+ const { data } = event;
585
723
  if (data.status === "done" || data.status === "canceled") {
586
724
  settle({ status: data.status });
587
725
  } else if (data.status === "error") {
@@ -624,7 +762,7 @@ export function parseRootKey(root: string): CloudProject | null {
624
762
  /** Every project this account can open, straight off the wire; [] when the catalogue is unreachable. */
625
763
  async function fetchProjects(): Promise<ProjectListWire[]> {
626
764
  const res = await fetch("/api/v1/projects", { credentials: "include" });
627
- return res.ok ? ((await res.json()) as ProjectListWire[]) : [];
765
+ return res.ok ? readJson<ProjectListWire[]>(res) : [];
628
766
  }
629
767
 
630
768
  /**
@@ -705,7 +843,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
705
843
  */
706
844
  const projectHint = project ? `${project.owner}/${project.repo}` : null;
707
845
 
708
- function postJson(path: string, body: unknown): Promise<Response> {
846
+ function postJson(path: string, body: JsonValue | FormatActionPayload): Promise<Response> {
709
847
  return api(path, {
710
848
  method: "POST",
711
849
  headers: { "Content-Type": "application/json" },
@@ -717,6 +855,21 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
717
855
  return okJson<ProjectInfoWire>(await api("/project-info"), "Failed to load project");
718
856
  }
719
857
 
858
+ /* The repository's default branch, asked once per session: it is what Send for review must never
859
+ commit to here, because a commit on this host lands on GitHub as it is made. A failed ask is
860
+ forgotten, so the next branch listing asks again. */
861
+ let defaultBranch: Promise<string> | null = null;
862
+ function repositoryDefaultBranch(): Promise<string> {
863
+ defaultBranch ??= projectInfo().then(
864
+ (info) => info.defaultBranch || "",
865
+ () => {
866
+ defaultBranch = null;
867
+ return "";
868
+ },
869
+ );
870
+ return defaultBranch;
871
+ }
872
+
720
873
  /** One file the old way: `GET /file`. What a single read, and the batch fallback, goes through. */
721
874
  async function readOne(path: string): Promise<string> {
722
875
  const data = await okJson<{ content: string }>(
@@ -752,16 +905,16 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
752
905
  if (!res.ok) {
753
906
  return "retry-singly";
754
907
  }
755
- let body: unknown;
908
+ let body: JsonValue;
756
909
  try {
757
- body = await res.json();
910
+ body = await readJson<JsonValue>(res);
758
911
  } catch {
759
912
  return "unsupported";
760
913
  }
761
- if (!body || typeof body !== "object" || !Array.isArray((body as ReadFilesResult).files)) {
914
+ if (!isReadFilesAnswer(body)) {
762
915
  return "unsupported";
763
916
  }
764
- return body as ReadFilesResult;
917
+ return body;
765
918
  },
766
919
  fetchOne: readOne,
767
920
  });
@@ -774,7 +927,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
774
927
  */
775
928
  let packageJsonRead: Promise<string> | null = null;
776
929
 
777
- async function readPackageJson(): Promise<Record<string, unknown>> {
930
+ async function readPackageJson(): Promise<JsonObject> {
778
931
  let text: string;
779
932
  try {
780
933
  packageJsonRead ??= reader.read("package.json").finally(() => {
@@ -786,13 +939,15 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
786
939
  }
787
940
  // Parsed per caller: the members mutate what they get, and must not mutate each other's copy.
788
941
  try {
789
- return JSON.parse(text) as Record<string, unknown>;
942
+ // A manifest that is not a JSON object is as unusable as one that is not JSON at all.
943
+ const pkg = parseJson(text);
944
+ return isJsonObject(pkg) ? pkg : {};
790
945
  } catch {
791
946
  return {};
792
947
  }
793
948
  }
794
949
 
795
- async function writePackageJson(pkg: Record<string, unknown>): Promise<void> {
950
+ async function writePackageJson(pkg: JsonObject): Promise<void> {
796
951
  const res = await api("/file", {
797
952
  method: "PUT",
798
953
  headers: { "Content-Type": "application/json" },
@@ -803,9 +958,20 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
803
958
  }
804
959
  }
805
960
 
961
+ // The bound session's /raw tree; see `documentBaseUrl` below for why both members ride together.
962
+ const repoAssets: Pick<StudioPlatform, "assetSpace" | "documentBaseUrl"> = {};
963
+ if (base) {
964
+ repoAssets.assetSpace = "repo";
965
+ repoAssets.documentBaseUrl = `${base}/raw/`;
966
+ }
967
+
806
968
  const platform: StudioPlatform = {
807
969
  id: "cloud",
808
970
  projectRoot: root,
971
+ /* Commits land on GitHub as they are made (`gitCommit`), a push is a sync check, and a branch
972
+ is a sibling session (`gitCheckout`), which is what the Publish workspace says before it
973
+ switches one (studio.md §22.8). */
974
+ gitHosted: true,
809
975
  canvasUrl: "/canvas.html",
810
976
  /* The projectRoot here is the IDENTIFIER "owner/repo@branch", not a served path, so the canvas's
811
977
  default base — <origin>/<projectRoot>/ — addressed nothing. Every component $ref fetch landed
@@ -822,7 +988,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
822
988
  broken, and logs nothing. Declaring "repo" tells Studio to resolve each reference to the
823
989
  project file it names and address it under /raw. Until a project is bound there is no /raw to
824
990
  address, so the project-less hub declares neither and stays exactly as it was. */
825
- ...(base ? { assetSpace: "repo" as const, documentBaseUrl: `${base}/raw/` } : {}),
991
+ ...repoAssets,
826
992
  /* Open Project routes through Studio's repo picker (write-access repos via listRepos +
827
993
  importProject) — sessions are URL-bound, so openProject() below never opens a dialog. */
828
994
  openProjectPicker: "repo-list",
@@ -851,7 +1017,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
851
1017
  return null;
852
1018
  }
853
1019
  const info = await projectInfo();
854
- const config = (info.projectConfig ?? {}) as ProjectConfig;
1020
+ const config: ProjectConfig = info.projectConfig ?? {};
855
1021
  return {
856
1022
  config,
857
1023
  handle: { root, name: config.name || info.name, projectConfig: config },
@@ -868,7 +1034,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
868
1034
  meta: { root, name: info.name },
869
1035
  info: {
870
1036
  isSiteProject: info.projectConfig !== null,
871
- projectConfig: (info.projectConfig as ProjectConfig | null) ?? null,
1037
+ projectConfig: info.projectConfig ?? null,
872
1038
  },
873
1039
  };
874
1040
  } catch {
@@ -920,7 +1086,11 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
920
1086
  const body = await okJson<Partial<UploadResult>>(res, `Upload failed: ${path}`);
921
1087
  // The session echoes the path today; falling back to the request keeps a backend that says
922
1088
  // Nothing working rather than writing `undefined` into a document.
923
- return { path: body.path ?? path, ...(body.size === undefined ? {} : { size: body.size }) };
1089
+ const uploaded: UploadResult = { path: body.path ?? path };
1090
+ if (body.size !== undefined) {
1091
+ uploaded.size = body.size;
1092
+ }
1093
+ return uploaded;
924
1094
  },
925
1095
 
926
1096
  async deleteFile(path: string) {
@@ -979,7 +1149,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
979
1149
  }
980
1150
  collabNegotiation ??= api("/collab")
981
1151
  .then(async (res) =>
982
- res.ok ? negotiateCollab(await res.json()) : { offer: [], refused: null },
1152
+ res.ok ? negotiateCollab(await readJson<JsonValue>(res)) : { offer: [], refused: null },
983
1153
  )
984
1154
  .catch(() => ({ offer: [], refused: null }));
985
1155
  const negotiated = await collabNegotiation;
@@ -1040,10 +1210,12 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1040
1210
  const scheme = location.protocol === "https:" ? "wss" : "ws";
1041
1211
  const ws = new WebSocket(`${scheme}://${location.host}${base}/events`);
1042
1212
  socket = ws;
1043
- ws.addEventListener("message", (ev: MessageEvent) => {
1213
+ ws.addEventListener("message", (ev: MessageEvent<string>) => {
1044
1214
  let payload: SessionEventWire;
1045
1215
  try {
1046
- payload = JSON.parse(ev.data as string) as SessionEventWire;
1216
+ /* SAFETY: the session's /events socket sends only text frames, each one a JSON
1217
+ SessionEventWire (`kind` "fs" with its events, or "git" with the git event). */
1218
+ payload = JSON.parse(ev.data) as SessionEventWire;
1047
1219
  } catch {
1048
1220
  return;
1049
1221
  }
@@ -1086,7 +1258,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1086
1258
  if (!res.ok) {
1087
1259
  return [];
1088
1260
  }
1089
- const body = (await res.json()) as { formats?: Record<string, unknown>[] };
1261
+ const body = await readJson<{ formats?: JsonObject[] }>(res);
1090
1262
  return body.formats ?? [];
1091
1263
  } catch {
1092
1264
  return [];
@@ -1100,7 +1272,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1100
1272
  if (!res.ok) {
1101
1273
  return [];
1102
1274
  }
1103
- const body = (await res.json()) as { extensions?: ExtensionsInfo[] };
1275
+ const body = await readJson<{ extensions?: ExtensionsInfo[] }>(res);
1104
1276
  return body.extensions ?? [];
1105
1277
  } catch {
1106
1278
  return [];
@@ -1130,11 +1302,11 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1130
1302
  if (!res.ok) {
1131
1303
  return [];
1132
1304
  }
1133
- const entries = (await res.json()) as ExtensionCatalogEntry[];
1305
+ const entries = await readJson<ExtensionCatalogEntry[]>(res);
1134
1306
  const pkg = await readPackageJson();
1135
1307
  const declared = new Set([
1136
- ...Object.keys((pkg["dependencies"] ?? {}) as Record<string, string>),
1137
- ...Object.keys((pkg["devDependencies"] ?? {}) as Record<string, string>),
1308
+ ...Object.keys(dependencyBlock(pkg, "dependencies")),
1309
+ ...Object.keys(dependencyBlock(pkg, "devDependencies")),
1138
1310
  ]);
1139
1311
  for (const entry of entries) {
1140
1312
  entry.bundled = true;
@@ -1161,7 +1333,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1161
1333
  if (!res.ok) {
1162
1334
  return {};
1163
1335
  }
1164
- return (await res.json()) as ProjectSchemasResponse;
1336
+ return await readJson<ProjectSchemasResponse>(res);
1165
1337
  } catch {
1166
1338
  return {};
1167
1339
  }
@@ -1173,7 +1345,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1173
1345
  * backends without the route surface the error below instead of silently mangling format
1174
1346
  * documents.
1175
1347
  */
1176
- async formatAction(payload: Record<string, unknown>) {
1348
+ async formatAction(payload) {
1177
1349
  const res = await postJson("/format", payload);
1178
1350
  if (!res.ok) {
1179
1351
  throw new Error(
@@ -1183,7 +1355,8 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1183
1355
  ),
1184
1356
  );
1185
1357
  }
1186
- const data = (await res.json()) as { result?: unknown };
1358
+ // A successful answer is `{ result }`: the parsed document, or the serialized text.
1359
+ const data = await readJson<{ result: JxMutableNode | string }>(res);
1187
1360
  return data.result;
1188
1361
  },
1189
1362
 
@@ -1242,12 +1415,15 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1242
1415
  const metas = await Promise.all(
1243
1416
  jsonPaths.map(async (path) => {
1244
1417
  try {
1245
- return componentMetaFrom(JSON.parse(await platform.readFile(path)), path);
1418
+ return componentMetaFrom(parseJson(await platform.readFile(path)), path);
1246
1419
  } catch {
1247
1420
  return null; // Not JSON, not readable, or not a component — all the same answer here.
1248
1421
  }
1249
1422
  }),
1250
1423
  );
1424
+ /* SAFETY: the two Bun backends answer discoverComponents with this same componentMetaFrom
1425
+ output, so ComponentMeta's narrower prop typing describes exactly what Studio already
1426
+ receives for these documents everywhere else. */
1251
1427
  return metas.filter((m): m is NonNullable<typeof m> => m !== null) as ComponentMeta[];
1252
1428
  },
1253
1429
 
@@ -1263,36 +1439,34 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1263
1439
 
1264
1440
  async addPackage(name: string) {
1265
1441
  const pkg = await readPackageJson();
1266
- const deps = (pkg["dependencies"] ?? {}) as Record<string, string>;
1442
+ const deps = dependencyBlock(pkg, "dependencies");
1267
1443
  const at = name.lastIndexOf("@");
1268
1444
  const [pkgName, version] =
1269
1445
  at > 0 ? [name.slice(0, at), name.slice(at + 1)] : [name, "latest"];
1270
1446
  deps[pkgName] = version;
1271
1447
  pkg["dependencies"] = deps;
1272
1448
  await writePackageJson(pkg);
1273
- return { ok: true, name: pkgName, version };
1274
1449
  },
1275
1450
 
1276
1451
  async removePackage(name: string) {
1277
1452
  const pkg = await readPackageJson();
1278
1453
  for (const key of ["dependencies", "devDependencies"]) {
1279
- const deps = pkg[key] as Record<string, string> | undefined;
1280
- if (deps && name in deps) {
1454
+ const deps = pkg[key];
1455
+ if (isJsonObject(deps) && name in deps) {
1281
1456
  pkg[key] = Object.fromEntries(Object.entries(deps).filter(([dep]) => dep !== name));
1282
1457
  }
1283
1458
  }
1284
1459
  await writePackageJson(pkg);
1285
- return { ok: true, name };
1286
1460
  },
1287
1461
 
1288
1462
  async listPackages(): Promise<PackageInfo[]> {
1289
1463
  const pkg = await readPackageJson();
1290
1464
  const out: PackageInfo[] = [];
1291
- const deps = (pkg["dependencies"] ?? {}) as Record<string, string>;
1465
+ const deps = dependencyBlock(pkg, "dependencies");
1292
1466
  for (const [name, version] of Object.entries(deps)) {
1293
1467
  out.push({ name, version });
1294
1468
  }
1295
- const devDeps = (pkg["devDependencies"] ?? {}) as Record<string, string>;
1469
+ const devDeps = dependencyBlock(pkg, "devDependencies");
1296
1470
  for (const [name, version] of Object.entries(devDeps)) {
1297
1471
  out.push({ name, version, dev: true });
1298
1472
  }
@@ -1304,12 +1478,15 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1304
1478
  async resolveSiteContext(filePath: string) {
1305
1479
  try {
1306
1480
  const info = await projectInfo();
1307
- const config = (info.projectConfig as ProjectConfig | null) ?? undefined;
1308
- return {
1309
- sitePath: root,
1310
- ...(config === undefined ? {} : { projectConfig: config }),
1311
- ...(filePath === root ? {} : { fileRelPath: filePath }),
1312
- };
1481
+ const config = info.projectConfig ?? undefined;
1482
+ const context: SiteContext = { sitePath: root };
1483
+ if (config !== undefined) {
1484
+ context.projectConfig = config;
1485
+ }
1486
+ if (filePath !== root) {
1487
+ context.fileRelPath = filePath;
1488
+ }
1489
+ return context;
1313
1490
  } catch {
1314
1491
  return { sitePath: null };
1315
1492
  }
@@ -1319,7 +1496,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1319
1496
  try {
1320
1497
  const res = await api(`/locate?name=${encodeURIComponent(name)}`);
1321
1498
  if (res.ok) {
1322
- const body = (await res.json()) as { path?: string | null };
1499
+ const body = await readJson<{ path?: string | null }>(res);
1323
1500
  return body.path ?? null;
1324
1501
  }
1325
1502
  } catch {
@@ -1336,7 +1513,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1336
1513
  if (!res.ok) {
1337
1514
  return [];
1338
1515
  }
1339
- return (await res.json()) as DirEntry[];
1516
+ return await readJson<DirEntry[]>(res);
1340
1517
  },
1341
1518
 
1342
1519
  // ─── Git (virtual engine in the ProjectSession DO) ─────────────────────
@@ -1346,7 +1523,15 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1346
1523
  },
1347
1524
 
1348
1525
  async gitBranches() {
1349
- return okJson<GitBranchesResult>(await api("/git/branches"), "Failed to list branches");
1526
+ const listed = await okJson<GitBranchesResult>(
1527
+ await api("/git/branches"),
1528
+ "Failed to list branches",
1529
+ );
1530
+ if (listed.defaultBranch) {
1531
+ return listed;
1532
+ }
1533
+ const name = await repositoryDefaultBranch();
1534
+ return name ? { ...listed, defaultBranch: name } : listed;
1350
1535
  },
1351
1536
 
1352
1537
  async gitLog(limit?: number) {
@@ -1458,7 +1643,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1458
1643
  if (!res.ok) {
1459
1644
  return [];
1460
1645
  }
1461
- return (await res.json()) as StarterInfo[];
1646
+ return await readJson<StarterInfo[]>(res);
1462
1647
  },
1463
1648
 
1464
1649
  /** Welcome/recents open path: navigate this tab into the project's editor. */
@@ -1531,14 +1716,14 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1531
1716
  missing App installation, the offered actions of an `action-required` refusal. */
1532
1717
  throw await platformError(res, "Failed to create project");
1533
1718
  }
1534
- const created = (await res.json()) as { owner: string; name: string; defaultBranch: string };
1719
+ const created = await readJson<{ owner: string; name: string; defaultBranch: string }>(res);
1535
1720
  return {
1536
1721
  root: projectRootKey({
1537
1722
  owner: created.owner,
1538
1723
  repo: created.name,
1539
1724
  branch: created.defaultBranch,
1540
1725
  }),
1541
- config: { name: opts.name } as ProjectConfig,
1726
+ config: { name: opts.name } satisfies ProjectConfig,
1542
1727
  };
1543
1728
  },
1544
1729
 
@@ -1576,17 +1761,20 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1576
1761
  if (!res.ok) {
1577
1762
  return null;
1578
1763
  }
1579
- const me = (await res.json()) as {
1764
+ const me = await readJson<{
1580
1765
  user: { login: string; name: string | null; avatar_url: string | null } | null;
1581
- };
1766
+ }>(res);
1582
1767
  if (!me.user) {
1583
1768
  return null;
1584
1769
  }
1585
- return {
1586
- login: me.user.login,
1587
- ...(me.user.name ? { name: me.user.name } : {}),
1588
- ...(me.user.avatar_url ? { avatarUrl: me.user.avatar_url } : {}),
1589
- };
1770
+ const user: SignedInUser = { login: me.user.login };
1771
+ if (me.user.name) {
1772
+ user.name = me.user.name;
1773
+ }
1774
+ if (me.user.avatar_url) {
1775
+ user.avatarUrl = me.user.avatar_url;
1776
+ }
1777
+ return user;
1590
1778
  },
1591
1779
 
1592
1780
  /** Repositories reachable through the user's Jx Suite App installations (user + org). */
@@ -1595,7 +1783,7 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1595
1783
  if (!res.ok) {
1596
1784
  throw new Error(await errorMessage(res, "Failed to list repositories"));
1597
1785
  }
1598
- const entries = (await res.json()) as (RepoInfo & { repoId: number })[];
1786
+ const entries = await readJson<(RepoInfo & { repoId: number })[]>(res);
1599
1787
  return entries.map((r) => ({
1600
1788
  owner: r.owner,
1601
1789
  name: r.name,
@@ -1636,24 +1824,29 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1636
1824
  if (dir === null) {
1637
1825
  throw new Error("The project folder must stay inside the repository.");
1638
1826
  }
1827
+ const importRequest: ImportProjectRequest = { owner: opts.owner, name: opts.name };
1828
+ if (dir) {
1829
+ importRequest.dir = dir;
1830
+ }
1639
1831
  const res = await fetch("/api/v1/projects/import", {
1640
1832
  method: "POST",
1641
1833
  credentials: "include",
1642
1834
  headers: { "Content-Type": "application/json" },
1643
- body: JSON.stringify({ owner: opts.owner, name: opts.name, ...(dir ? { dir } : {}) }),
1835
+ body: JSON.stringify(importRequest),
1644
1836
  });
1645
1837
  const imported = await okJson<{ owner: string; name: string; defaultBranch: string }>(
1646
1838
  res,
1647
1839
  "Failed to import repository",
1648
1840
  );
1649
- return {
1650
- root: projectRootKey({
1651
- owner: imported.owner,
1652
- repo: imported.name,
1653
- branch: imported.defaultBranch,
1654
- ...(dir ? { dir } : {}),
1655
- }),
1841
+ const importedProject: CloudProject = {
1842
+ owner: imported.owner,
1843
+ repo: imported.name,
1844
+ branch: imported.defaultBranch,
1656
1845
  };
1846
+ if (dir) {
1847
+ importedProject.dir = dir;
1848
+ }
1849
+ return { root: projectRootKey(importedProject) };
1657
1850
  },
1658
1851
 
1659
1852
  /**
@@ -1667,10 +1860,10 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1667
1860
  if (!res.ok) {
1668
1861
  return null;
1669
1862
  }
1670
- const me = (await res.json()) as MeWire;
1863
+ const me = await readJson<MeWire>(res);
1671
1864
  const entries = accountEntries(me.entries);
1672
1865
  const notices = accountNotices(me.notices);
1673
- return {
1866
+ const status: AccountStatus = {
1674
1867
  installations: (me.installations ?? []).map((entry) => {
1675
1868
  const installation: AccountStatus["installations"][number] = {
1676
1869
  id: entry.id,
@@ -1681,10 +1874,17 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1681
1874
  }
1682
1875
  return installation;
1683
1876
  }),
1684
- ...(me.appInstallUrl ? { appInstallUrl: me.appInstallUrl } : {}),
1685
- ...(entries.length > 0 ? { entries } : {}),
1686
- ...(notices.length > 0 ? { notices } : {}),
1687
1877
  };
1878
+ if (me.appInstallUrl) {
1879
+ status.appInstallUrl = me.appInstallUrl;
1880
+ }
1881
+ if (entries.length > 0) {
1882
+ status.entries = entries;
1883
+ }
1884
+ if (notices.length > 0) {
1885
+ status.notices = notices;
1886
+ }
1887
+ return status;
1688
1888
  },
1689
1889
 
1690
1890
  /**
@@ -1823,34 +2023,31 @@ export function createCloudPlatform(project: CloudProject | null): StudioPlatfor
1823
2023
  async cfApi(apiPath: string, init?: { method?: string; body?: unknown }) {
1824
2024
  /* The project rides in a HEADER, never the query: the platform forwards this path's query
1825
2025
  string to Cloudflare verbatim. */
1826
- const headers: Record<string, string> = {
1827
- ...(projectHint ? { "X-Jx-Project": projectHint } : {}),
1828
- ...(init?.body === undefined ? {} : { "Content-Type": "application/json" }),
1829
- };
1830
- const res = await fetch(`/api/v1/cf/proxy${apiPath}`, {
1831
- method: init?.method ?? "GET",
1832
- credentials: "include",
1833
- ...(Object.keys(headers).length === 0 ? {} : { headers }),
1834
- ...(init?.body === undefined ? {} : { body: JSON.stringify(init.body) }),
1835
- });
2026
+ const headers: Record<string, string> = {};
2027
+ if (projectHint) {
2028
+ headers["X-Jx-Project"] = projectHint;
2029
+ }
2030
+ if (init?.body !== undefined) {
2031
+ headers["Content-Type"] = "application/json";
2032
+ }
2033
+ const request: RequestInit = { method: init?.method ?? "GET", credentials: "include" };
2034
+ if (Object.keys(headers).length > 0) {
2035
+ request.headers = headers;
2036
+ }
2037
+ if (init?.body !== undefined) {
2038
+ request.body = JSON.stringify(init.body);
2039
+ }
2040
+ const res = await fetch(`/api/v1/cf/proxy${apiPath}`, request);
1836
2041
  /* An `action-required` refusal is the platform's answer, not Cloudflare's, so it is not
1837
2042
  dressed as one: it keeps its own sentence and the actions the publish flow offers. Read
1838
2043
  from a clone, because every other 403 is Cloudflare's own and is parsed below. */
1839
2044
  if (res.status === 403) {
1840
- const refusal = (await res
1841
- .clone()
1842
- .json()
1843
- .catch(() => null)) as StructuredBody | null;
2045
+ const refusal = await readJson<StructuredBody | null>(res.clone()).catch(() => null);
1844
2046
  if (isActionRequiredBody(refusal)) {
1845
2047
  throw await platformError(res, "Publishing was refused");
1846
2048
  }
1847
2049
  }
1848
- const envelope = (await res.json()) as {
1849
- success?: boolean;
1850
- result?: unknown;
1851
- errors?: { message: string }[];
1852
- error?: string;
1853
- };
2050
+ const envelope = await readJson<CfProxyEnvelope>(res);
1854
2051
  if (!res.ok || envelope.success === false) {
1855
2052
  const message =
1856
2053
  envelope.errors?.map((e) => e.message).join("; ") ?? envelope.error ?? res.statusText;