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