@volter/editor-core 0.5.57
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/BUNDLED_NOTICES +1527 -0
- package/LICENSE +686 -0
- package/LICENSE-APACHE +202 -0
- package/NOTICE +18 -0
- package/README.md +24 -0
- package/dist/build/chunk-JS4D4XZ3.js +175 -0
- package/dist/build/chunk-JS4D4XZ3.js.map +7 -0
- package/dist/build/vite-plugin-product-contributions.js +100 -0
- package/dist/build/vite-plugin-product-contributions.js.map +7 -0
- package/dist/build/vite-plugin-shared-react.js +25 -0
- package/dist/build/vite-plugin-shared-react.js.map +7 -0
- package/dist/build/vite-plugin-shared-three.js +86 -0
- package/dist/build/vite-plugin-shared-three.js.map +7 -0
- package/dist/server/chunk-KMJC7AGO.js +98 -0
- package/dist/server/chunk-KMJC7AGO.js.map +7 -0
- package/dist/server/chunk-PSILUMGS.js +46 -0
- package/dist/server/chunk-PSILUMGS.js.map +7 -0
- package/dist/server/frame-proxy.js +255 -0
- package/dist/server/frame-proxy.js.map +7 -0
- package/dist/server/open-browser.js +53 -0
- package/dist/server/open-browser.js.map +7 -0
- package/dist/server/process-shutdown.js +127 -0
- package/dist/server/process-shutdown.js.map +7 -0
- package/dist/server/session-registry.js +141 -0
- package/dist/server/session-registry.js.map +7 -0
- package/dist/server/spawn-opener.js +11 -0
- package/dist/server/spawn-opener.js.map +7 -0
- package/dist/server/worktree-identity.js +11 -0
- package/dist/server/worktree-identity.js.map +7 -0
- package/dist-server/packaged.mjs +88816 -0
- package/package.json +118 -0
- package/scripts/build-plugins.mjs +14 -0
- package/scripts/build-server.mjs +26 -0
- package/scripts/build-session.mjs +9 -0
- package/server/account-credentials.ts +60 -0
- package/server/account-service.ts +1434 -0
- package/server/adapter-region-includes.ts +47 -0
- package/server/asset-catalog-v2.ts +175 -0
- package/server/asset-history-snapshots.ts +196 -0
- package/server/asset-ledger-store.ts +195 -0
- package/server/asset-library-routes.ts +1595 -0
- package/server/blender-wasm-artifact.ts +430 -0
- package/server/boot-timings.ts +106 -0
- package/server/canonical-path.ts +50 -0
- package/server/checkout-workspace-preflight.ts +349 -0
- package/server/cloud-asset-catalog.ts +158 -0
- package/server/coding-inference-launch.ts +237 -0
- package/server/collaboration-account-client.ts +202 -0
- package/server/collaboration-attribution.ts +122 -0
- package/server/collaboration-session.ts +934 -0
- package/server/comfyui-bridge.ts +248 -0
- package/server/console-ledger.ts +499 -0
- package/server/creation-site-transform.ts +304 -0
- package/server/creation-site-write.ts +648 -0
- package/server/data-file-serialize.ts +158 -0
- package/server/editor-brand-html.ts +72 -0
- package/server/editor-control-socket.ts +366 -0
- package/server/editor-server-options.ts +190 -0
- package/server/editor-server.ts +1483 -0
- package/server/editor-sse.ts +352 -0
- package/server/engine-provenance.ts +169 -0
- package/server/engine-source-restart.ts +117 -0
- package/server/frame-bridge.ts +115 -0
- package/server/frame-proxy.ts +490 -0
- package/server/frame-workbench.ts +259 -0
- package/server/frontend-handoff.ts +229 -0
- package/server/game-globals-shadow.ts +113 -0
- package/server/gameplay-session-retention.ts +149 -0
- package/server/gameplay-sessions.ts +123 -0
- package/server/generation-jobs.ts +201 -0
- package/server/generation-reconciler.ts +137 -0
- package/server/generative-execution-context.ts +59 -0
- package/server/git-workflow.ts +612 -0
- package/server/harness-chat-caller.ts +36 -0
- package/server/harness-chat-service.ts +1681 -0
- package/server/idle-shutdown.ts +170 -0
- package/server/js-profiling-policy.ts +52 -0
- package/server/launcher-settings.ts +84 -0
- package/server/local-asset-catalog.ts +410 -0
- package/server/managed-account-defaults.ts +22 -0
- package/server/mock-control-plane.ts +540 -0
- package/server/model-import-conversion.ts +345 -0
- package/server/native-credential-store.ts +162 -0
- package/server/open-browser.ts +118 -0
- package/server/packaged.ts +1192 -0
- package/server/play-stall.ts +126 -0
- package/server/process-shutdown.ts +218 -0
- package/server/product-presets.ts +55 -0
- package/server/project-build-artifact.ts +95 -0
- package/server/project-components.ts +100 -0
- package/server/project-dependency-invalidation.ts +114 -0
- package/server/project-file-scan.ts +235 -0
- package/server/project-hmr-files.ts +215 -0
- package/server/project-install-roots.ts +210 -0
- package/server/project-kinds.ts +71 -0
- package/server/project-mcp-servers.ts +82 -0
- package/server/project-module-freshness.ts +109 -0
- package/server/project-module-instance.ts +375 -0
- package/server/project-optimize-deps-entries.ts +827 -0
- package/server/project-output-writer.ts +679 -0
- package/server/project-package-origin.ts +63 -0
- package/server/project-root-surface.ts +831 -0
- package/server/project-scratch-path.ts +47 -0
- package/server/project-script-hmr.ts +619 -0
- package/server/project-serving-plugins.ts +236 -0
- package/server/project-tools.ts +653 -0
- package/server/project-validation.ts +250 -0
- package/server/project-verbs.ts +127 -0
- package/server/project-view.ts +52 -0
- package/server/project-watch.ts +1134 -0
- package/server/project-work-coordinator.ts +288 -0
- package/server/provider-credentials.ts +331 -0
- package/server/recent-projects-store.ts +98 -0
- package/server/redact-secrets.ts +71 -0
- package/server/repository-presence.ts +267 -0
- package/server/routes/account.ts +357 -0
- package/server/routes/agents.ts +60 -0
- package/server/routes/assets.ts +154 -0
- package/server/routes/build.ts +13 -0
- package/server/routes/collaboration.ts +595 -0
- package/server/routes/configurations.ts +419 -0
- package/server/routes/context.ts +264 -0
- package/server/routes/control-plane.ts +1811 -0
- package/server/routes/logs.ts +272 -0
- package/server/routes/project-identity.ts +302 -0
- package/server/routes/project-open.ts +429 -0
- package/server/routes/project-source.ts +686 -0
- package/server/routes/project-state.ts +383 -0
- package/server/routes/relay.ts +1029 -0
- package/server/routes/route-helpers.ts +29 -0
- package/server/routes/served-modules.ts +138 -0
- package/server/routes/session-tabs.ts +196 -0
- package/server/routes/settings.ts +121 -0
- package/server/routes/share-control.ts +486 -0
- package/server/routes/themes.ts +116 -0
- package/server/routes/tools.ts +230 -0
- package/server/routes/worktrees.ts +595 -0
- package/server/scoped-game-css.ts +461 -0
- package/server/server-utils.ts +1194 -0
- package/server/session-product.ts +112 -0
- package/server/session-registry.ts +230 -0
- package/server/share-claims.ts +138 -0
- package/server/share-host.ts +526 -0
- package/server/share-session-gateway.ts +1362 -0
- package/server/share-tunnel.ts +123 -0
- package/server/spawn-opener.ts +74 -0
- package/server/support/play/log-format.ts +76 -0
- package/server/support/play/session-record.ts +199 -0
- package/server/support/project/build-discipline.ts +718 -0
- package/server/support/project/inspection-node.ts +119 -0
- package/server/support/project/log-naming.ts +54 -0
- package/server/support/project/provenance.ts +290 -0
- package/server/support/project/run-name.ts +18 -0
- package/server/support/project/session-journal.ts +830 -0
- package/server/support/project/shared.ts +327 -0
- package/server/tab-bootstrap.ts +62 -0
- package/server/tab-heartbeat.ts +477 -0
- package/server/tab-lifecycle.ts +550 -0
- package/server/tab-presence.ts +1508 -0
- package/server/team-agent-mirror.ts +95 -0
- package/server/twin-auth.ts +138 -0
- package/server/vendored-lock-recorder.ts +968 -0
- package/server/worktree-identity.ts +121 -0
- package/server/worktree-management.ts +398 -0
- package/server/worktree-retention.d.mts +13 -0
- package/server/worktree-retention.mjs +205 -0
- package/src/EditorContext.tsx +169 -0
- package/src/account.ts +333 -0
- package/src/action-registry.ts +532 -0
- package/src/active-product.ts +74 -0
- package/src/active-project.ts +155 -0
- package/src/adapter-editor-config.ts +25 -0
- package/src/adapter-observation.ts +49 -0
- package/src/animation/stage-transport.ts +379 -0
- package/src/animation/three-clips-subject.ts +172 -0
- package/src/api/asset-library-wire.ts +45 -0
- package/src/api/assets.ts +365 -0
- package/src/api/base.ts +10 -0
- package/src/api/build.ts +99 -0
- package/src/api/git-wire.ts +56 -0
- package/src/api/logs.ts +92 -0
- package/src/api/project-identity.ts +74 -0
- package/src/api/project-open.ts +355 -0
- package/src/api/project-source.ts +162 -0
- package/src/api/project-state.ts +107 -0
- package/src/api/relay.ts +268 -0
- package/src/api/settings.ts +36 -0
- package/src/api/themes.ts +45 -0
- package/src/api/worktrees.ts +257 -0
- package/src/asset-compare-core.ts +171 -0
- package/src/asset-compare.ts +294 -0
- package/src/asset-editor-context.tsx +100 -0
- package/src/asset-events.ts +97 -0
- package/src/asset-inspector-actions.ts +87 -0
- package/src/asset-preview-framing.ts +357 -0
- package/src/asset-preview.ts +2802 -0
- package/src/asset-selection-viewer-registry.ts +113 -0
- package/src/asset-selection.ts +133 -0
- package/src/asset-workflow/asset-capabilities.ts +344 -0
- package/src/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/asset-workflow/asset-ledger.ts +156 -0
- package/src/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/asset-workflow/asset-types.ts +142 -0
- package/src/asset-workflow/asset-workflow-quality.ts +61 -0
- package/src/asset-workflow/audio-preview-player.ts +193 -0
- package/src/asset-workflow/audio-waveform.ts +22 -0
- package/src/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/asset-workflow/folder-preview.ts +345 -0
- package/src/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/asset-workflow/image-view-scale.ts +32 -0
- package/src/asset-workflow/import-contract.ts +124 -0
- package/src/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/asset-workflow/model-inspection.ts +818 -0
- package/src/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/asset-workflow/project-asset-commands.ts +23 -0
- package/src/asset-workflow/project-asset-health.ts +139 -0
- package/src/asset-workflow/project-asset-operations.ts +154 -0
- package/src/asset-workflow/project-asset-roots.ts +68 -0
- package/src/asset-workflow/project-content.ts +288 -0
- package/src/asset-workflow/project-source-index.ts +550 -0
- package/src/asset-workflow/thumbnail-system.ts +256 -0
- package/src/authoring/active-adapter.ts +199 -0
- package/src/authoring/active-systems.ts +422 -0
- package/src/authoring/adapter-key.ts +18 -0
- package/src/authoring/authoring-asset-url.ts +27 -0
- package/src/authoring/bootstrap-state.ts +49 -0
- package/src/authoring/boundary-authoring-adapter.ts +184 -0
- package/src/authoring/breakpoint-state.ts +43 -0
- package/src/authoring/canvas-scene-guides.ts +76 -0
- package/src/authoring/component-instance-root.ts +171 -0
- package/src/authoring/composite-authoring-adapter.ts +2110 -0
- package/src/authoring/consumer-actions.ts +520 -0
- package/src/authoring/css-numeric-style.ts +97 -0
- package/src/authoring/design-time-layers.ts +849 -0
- package/src/authoring/design-time-mount-registry.ts +235 -0
- package/src/authoring/design-time-settle.ts +343 -0
- package/src/authoring/edit-mode-authoring.ts +619 -0
- package/src/authoring/eyedropper-session.ts +60 -0
- package/src/authoring/instance-source-menu-register.ts +13 -0
- package/src/authoring/instance-source-menu.ts +135 -0
- package/src/authoring/layered-pick.ts +183 -0
- package/src/authoring/live-gesture-lock.ts +50 -0
- package/src/authoring/live-object-transform.ts +62 -0
- package/src/authoring/mount-failure-report.ts +154 -0
- package/src/authoring/mounted-root-subjects.ts +144 -0
- package/src/authoring/no-authoring-adapter.ts +55 -0
- package/src/authoring/null-inspection-subjects.tsx +75 -0
- package/src/authoring/object3d-document-persistence.ts +106 -0
- package/src/authoring/object3d-document-session-registry.ts +120 -0
- package/src/authoring/object3d-document-session.ts +1326 -0
- package/src/authoring/object3d-gesture-controller.ts +113 -0
- package/src/authoring/panel-authoring.ts +121 -0
- package/src/authoring/prefab-instance-inspector-section.tsx +237 -0
- package/src/authoring/prefab-instance-section-model.ts +55 -0
- package/src/authoring/project-authoring-session.ts +105 -0
- package/src/authoring/provenance.ts +99 -0
- package/src/authoring/quarks-particle-systems.ts +19 -0
- package/src/authoring/react-canvas-navigation.ts +255 -0
- package/src/authoring/react-design-canvas-style.ts +20 -0
- package/src/authoring/react-story-board.ts +937 -0
- package/src/authoring/selection-scope.ts +195 -0
- package/src/authoring/shell-document-ops.ts +169 -0
- package/src/authoring/shell-object3d-document-write-policy.ts +108 -0
- package/src/authoring/shell-viewport-policy.ts +48 -0
- package/src/authoring/source-object3d-authoring-adapter.ts +526 -0
- package/src/authoring/stories-scope.ts +35 -0
- package/src/authoring/story-board-chrome-fit.ts +107 -0
- package/src/authoring/story-board-presentation.ts +111 -0
- package/src/authoring/three-projection-core.ts +226 -0
- package/src/authoring/viewport-pick-context.ts +40 -0
- package/src/authoring/viewport-raycast.ts +240 -0
- package/src/authoring/viewport-tool-context.ts +73 -0
- package/src/authoring/world-canvas-viewport-state.ts +35 -0
- package/src/authoring/world-hidden-viewport.ts +152 -0
- package/src/authoring/world-pan-state.ts +198 -0
- package/src/authoring/world-session-state.ts +101 -0
- package/src/authoring/write-pipe.ts +173 -0
- package/src/availability-tick.ts +66 -0
- package/src/bitmap-label.ts +120 -0
- package/src/blender-tab-metrics.ts +161 -0
- package/src/board-open-actions.ts +20 -0
- package/src/boot-routing.ts +391 -0
- package/src/build-identity.ts +15 -0
- package/src/bytes-codec.ts +62 -0
- package/src/camera-authoring.ts +175 -0
- package/src/cancellation-reason.ts +58 -0
- package/src/canvas-preview-frames.ts +482 -0
- package/src/capture-camera-pose.ts +77 -0
- package/src/chrome-registry.ts +159 -0
- package/src/chrome-slot-registry.ts +91 -0
- package/src/collaboration-client.ts +264 -0
- package/src/collaboration-presence.ts +41 -0
- package/src/command-dispatch.ts +19 -0
- package/src/command-listener.ts +2743 -0
- package/src/command-registry.ts +70 -0
- package/src/component-board-registry.ts +205 -0
- package/src/component-states-registry.ts +200 -0
- package/src/components/AgentPresentationNotice.tsx +75 -0
- package/src/components/AlignToolbar.tsx +204 -0
- package/src/components/AppRoot.tsx +394 -0
- package/src/components/ApplicationMenus.tsx +415 -0
- package/src/components/AssetBrowser.tsx +2843 -0
- package/src/components/AssetEditorShell.tsx +216 -0
- package/src/components/AssetInspectorToolSection.tsx +124 -0
- package/src/components/BoardRulers.tsx +354 -0
- package/src/components/CameraInfo.tsx +81 -0
- package/src/components/CanvasSceneViewport.tsx +556 -0
- package/src/components/CapabilityCoverageSection.tsx +185 -0
- package/src/components/CenterDocuments.tsx +22 -0
- package/src/components/ChromeSlot.tsx +20 -0
- package/src/components/CodeView.tsx +470 -0
- package/src/components/CollaborationHeaderControl.css +74 -0
- package/src/components/CompactInspectorCard.tsx +190 -0
- package/src/components/CompactInspectorShell.tsx +39 -0
- package/src/components/ConsolePanel.css +55 -0
- package/src/components/ConsolePanel.tsx +270 -0
- package/src/components/DefaultEditorLayout.tsx +106 -0
- package/src/components/DocumentHeaderStrip.tsx +96 -0
- package/src/components/DocumentShelfRail.tsx +45 -0
- package/src/components/DocumentThumbnail.tsx +345 -0
- package/src/components/EditorLeaseGuard.tsx +372 -0
- package/src/components/ErrorBanner.tsx +123 -0
- package/src/components/FolderPreviewTile.tsx +159 -0
- package/src/components/GameHierarchy.tsx +3842 -0
- package/src/components/GameplaySessionTimeline.tsx +295 -0
- package/src/components/InspectionProjection.tsx +968 -0
- package/src/components/Inspector.tsx +233 -0
- package/src/components/InspectorCanvasPreview.tsx +35 -0
- package/src/components/InspectorFieldsSection.tsx +290 -0
- package/src/components/InspectorObjectPreview.tsx +57 -0
- package/src/components/InspectorStoriesSection.tsx +92 -0
- package/src/components/InspectorToolSection.tsx +96 -0
- package/src/components/InspectorTransformSection.tsx +245 -0
- package/src/components/LightExplorerPanel.tsx +433 -0
- package/src/components/MediaProperties.tsx +145 -0
- package/src/components/NonThreeAuthoringBootstrap.tsx +19 -0
- package/src/components/Object3DDocumentToolbar.css +100 -0
- package/src/components/Object3DDocumentToolbar.tsx +454 -0
- package/src/components/Object3DDocumentViewport.tsx +58 -0
- package/src/components/ProjectHeader.css +617 -0
- package/src/components/ProjectHeader.tsx +328 -0
- package/src/components/ProjectLayout.tsx +249 -0
- package/src/components/ReactCanvasControls.tsx +284 -0
- package/src/components/RootSelectionOverlay.tsx +3162 -0
- package/src/components/RootTextEditor.tsx +79 -0
- package/src/components/SaveStatus.tsx +70 -0
- package/src/components/StageHost.tsx +1954 -0
- package/src/components/StageOverlays.tsx +21 -0
- package/src/components/StartupErrorScreen.tsx +76 -0
- package/src/components/StartupLoadingScreen.tsx +65 -0
- package/src/components/StatsOverlay.tsx +78 -0
- package/src/components/SurfaceStateOverlay.tsx +24 -0
- package/src/components/ToolContributionSurfaces.tsx +65 -0
- package/src/components/ToolHost.tsx +370 -0
- package/src/components/ToolObject3DPreview.tsx +39 -0
- package/src/components/Toolbar.tsx +595 -0
- package/src/components/TransientHint.tsx +44 -0
- package/src/components/TransportStrip.tsx +174 -0
- package/src/components/VersionControlSection.tsx +470 -0
- package/src/components/VgaiLogo.css +83 -0
- package/src/components/VgaiLogo.tsx +35 -0
- package/src/components/ViewportControlsHint.tsx +60 -0
- package/src/components/ViewportFurniture.tsx +401 -0
- package/src/components/ViewportOverlay.tsx +145 -0
- package/src/components/ViewportOverlaysMenu.tsx +153 -0
- package/src/components/ViewportShadingMenu.tsx +300 -0
- package/src/components/ViewportViewMenu.tsx +101 -0
- package/src/components/WorkspaceDocumentSurface.tsx +204 -0
- package/src/components/WorkspaceUtilitySurface.tsx +22 -0
- package/src/components/WorktreeSwitcher.css +239 -0
- package/src/components/WorktreeSwitcher.tsx +890 -0
- package/src/components/account-documents.tsx +1162 -0
- package/src/components/asset-documents.tsx +812 -0
- package/src/components/asset-editor-persistence.ts +216 -0
- package/src/components/asset-selection-section.tsx +535 -0
- package/src/components/asset-thumbnails.tsx +312 -0
- package/src/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/components/asset-viewers/EntityModelDocument.tsx +122 -0
- package/src/components/asset-viewers/EnvironmentAssetDocument.tsx +440 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/components/asset-viewers/JsonAssetDocument.tsx +93 -0
- package/src/components/asset-viewers/LiveModuleDocument.tsx +417 -0
- package/src/components/asset-viewers/LutAssetDocument.tsx +444 -0
- package/src/components/asset-viewers/ModelAssetDocument.tsx +105 -0
- package/src/components/asset-viewers/Object3DPreview.tsx +359 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +421 -0
- package/src/components/asset-viewers/PasteboardModuleDocument.tsx +67 -0
- package/src/components/asset-viewers/QuarksAssetDocument.tsx +526 -0
- package/src/components/asset-viewers/ShaderAssetDocument.tsx +743 -0
- package/src/components/asset-viewers/SourceAssetViewer.tsx +281 -0
- package/src/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/components/asset-viewers/shader-source.ts +144 -0
- package/src/components/asset-workflow.css +731 -0
- package/src/components/board-guides.ts +150 -0
- package/src/components/compact-inspector.css +539 -0
- package/src/components/core-utilities.tsx +90 -0
- package/src/components/editor-notifications.css +40 -0
- package/src/components/engine-workspace.css +274 -0
- package/src/components/inspector-preview-section.tsx +238 -0
- package/src/components/inspector-property-grouping.ts +64 -0
- package/src/components/inspector-revert-label.ts +20 -0
- package/src/components/inspector-selection.ts +42 -0
- package/src/components/inspector-stories-gating.ts +171 -0
- package/src/components/inspector-transform-subject.ts +11 -0
- package/src/components/inspector-transform.ts +75 -0
- package/src/components/kind-documents.tsx +500 -0
- package/src/components/palette-action-publisher.tsx +140 -0
- package/src/components/primitives/DraftColorInput.tsx +74 -0
- package/src/components/product-shell.css +1829 -0
- package/src/components/project-tool-documents.tsx +410 -0
- package/src/components/scene-documents.tsx +223 -0
- package/src/components/stage-keyboard.tsx +37 -0
- package/src/components/stage-overlay-set.tsx +107 -0
- package/src/components/stage-presence-markers.ts +478 -0
- package/src/components/standard-viewport-dressing.ts +417 -0
- package/src/components/status-contributions.tsx +403 -0
- package/src/components/tool-documents.tsx +309 -0
- package/src/components/tool-schema-form.tsx +262 -0
- package/src/components/use-after-paint.ts +41 -0
- package/src/components/use-project-image-assets.ts +86 -0
- package/src/components/viewport-header-controls.css +90 -0
- package/src/components/viewport-surface-status.tsx +55 -0
- package/src/components/workspace-history.ts +32 -0
- package/src/components/workspace-static-panel-registry.tsx +152 -0
- package/src/components/workspace-surfaces.css +621 -0
- package/src/components/world-documents.tsx +586 -0
- package/src/components/world-overlay-gestures.ts +1694 -0
- package/src/composite-screenshot.ts +1641 -0
- package/src/console-sync.ts +131 -0
- package/src/constraint-helper.ts +338 -0
- package/src/content-entry-source-registry.ts +184 -0
- package/src/coverage/authoring-seam-evidence.ts +300 -0
- package/src/coverage/canvas-reveal.ts +192 -0
- package/src/coverage/design-time-surfaces.ts +101 -0
- package/src/coverage/live-seam-evidence.ts +11 -0
- package/src/coverage/ontology-invariants.ts +466 -0
- package/src/coverage/session-vitals.ts +501 -0
- package/src/coverage/system-seam-evidence.ts +72 -0
- package/src/crash-null-boundary.ts +36 -0
- package/src/creation-site-edit.ts +1479 -0
- package/src/creation-site-registry.ts +160 -0
- package/src/delegate-harness-registry.ts +143 -0
- package/src/document-context-registry.ts +177 -0
- package/src/document-open-registry.ts +200 -0
- package/src/document-preview-source.ts +20 -0
- package/src/document-renderer-session.ts +138 -0
- package/src/editor-api.ts +46 -0
- package/src/editor-chrome-capture.ts +139 -0
- package/src/editor-commands.ts +164 -0
- package/src/editor-console.ts +563 -0
- package/src/editor-current-view.ts +82 -0
- package/src/editor-document-probe.ts +881 -0
- package/src/editor-git-client.ts +115 -0
- package/src/editor-host-door.ts +462 -0
- package/src/editor-hotkeys.ts +842 -0
- package/src/editor-lease-view.ts +39 -0
- package/src/editor-lease.ts +415 -0
- package/src/editor-mode.ts +19 -0
- package/src/editor-notifications.ts +140 -0
- package/src/editor-presence.ts +563 -0
- package/src/editor-presentation-activity.ts +50 -0
- package/src/editor-presentation-notice.ts +42 -0
- package/src/editor-runtime.tsx +145 -0
- package/src/editor-server-response.ts +86 -0
- package/src/editor-session-attribution.ts +75 -0
- package/src/editor-session-mode.ts +54 -0
- package/src/editor-shell-store.ts +1304 -0
- package/src/editor-state-facets.ts +74 -0
- package/src/editor-styles.css +33 -0
- package/src/editor-view-presentation.ts +810 -0
- package/src/editor-viewport.ts +5302 -0
- package/src/entity-lod.ts +31 -0
- package/src/entity-object.ts +91 -0
- package/src/files/file-provider.ts +62 -0
- package/src/files/project-files.ts +264 -0
- package/src/finders/index.ts +136 -0
- package/src/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/frame/bridge.tsx +1408 -0
- package/src/frame/product.ts +77 -0
- package/src/gameplay-dom-recording.ts +319 -0
- package/src/gameplay-export-state.ts +14 -0
- package/src/gameplay-replay.ts +417 -0
- package/src/gameplay-session-time.ts +9 -0
- package/src/gameplay-sessions.ts +204 -0
- package/src/harness-chat-types.ts +253 -0
- package/src/hierarchy-component-marks.ts +298 -0
- package/src/hierarchy-drop.ts +91 -0
- package/src/hierarchy-expansion-state.ts +80 -0
- package/src/hierarchy-header-slot.ts +52 -0
- package/src/hierarchy-internals.ts +197 -0
- package/src/hierarchy-kind-icon.ts +217 -0
- package/src/hierarchy-mark-reader.ts +73 -0
- package/src/hierarchy-menu-registry.ts +67 -0
- package/src/hierarchy-node-rows.ts +307 -0
- package/src/hierarchy-panel-view.ts +280 -0
- package/src/hierarchy-projection.ts +76 -0
- package/src/hierarchy-row-cache.ts +243 -0
- package/src/hierarchy-row-model.ts +308 -0
- package/src/hierarchy-rows.ts +11 -0
- package/src/hierarchy-walk.ts +86 -0
- package/src/history/editor-session.ts +25 -0
- package/src/history/history-commands.ts +147 -0
- package/src/history/history-delegate.ts +163 -0
- package/src/history/history-limit-notices.ts +43 -0
- package/src/history/history-service.ts +1173 -0
- package/src/history/persistence-coordinator.ts +35 -0
- package/src/history/project-file-history.ts +386 -0
- package/src/history/project-root-history-backends.ts +139 -0
- package/src/history/resource-registry.ts +209 -0
- package/src/history/snapshot-store.ts +103 -0
- package/src/history/source-history-backend.ts +546 -0
- package/src/history/types.ts +124 -0
- package/src/hmr-registration-group.ts +67 -0
- package/src/hmr-stable-react-context.ts +23 -0
- package/src/hotkeys.ts +188 -0
- package/src/inference-diagnostics.ts +69 -0
- package/src/initial-project.ts +80 -0
- package/src/inspection/active-subject.ts +578 -0
- package/src/inspection/active-surface.ts +142 -0
- package/src/inspection/compose.ts +1064 -0
- package/src/inspection/display.ts +170 -0
- package/src/inspection/document-subject.ts +109 -0
- package/src/inspection/game-subject.ts +85 -0
- package/src/inspection/model.ts +542 -0
- package/src/inspection/null-subject.ts +115 -0
- package/src/inspection/serialize.ts +357 -0
- package/src/inspection/use-active-inspection.ts +180 -0
- package/src/inspector-presentation.ts +201 -0
- package/src/inspector-section-registry.ts +221 -0
- package/src/instance-source-actions.ts +163 -0
- package/src/instanced-presentation.ts +164 -0
- package/src/js-heap.ts +71 -0
- package/src/key-actions.ts +91 -0
- package/src/keymap-presets.ts +401 -0
- package/src/layout-policy.ts +31 -0
- package/src/learn-links.ts +73 -0
- package/src/light-explorer-model.ts +134 -0
- package/src/live-canvas-frame.ts +55 -0
- package/src/live-document.ts +279 -0
- package/src/live-module-source.ts +230 -0
- package/src/live-session-registry.ts +220 -0
- package/src/live-transition.ts +633 -0
- package/src/manifest-project.ts +107 -0
- package/src/model-thumbnail.ts +523 -0
- package/src/native-selection-style.ts +202 -0
- package/src/object3d-document-write-policy.ts +137 -0
- package/src/packaged-runtime.ts +108 -0
- package/src/palettes/maya.palette.json +57 -0
- package/src/palettes/substance.palette.json +57 -0
- package/src/pasteboard-module.ts +81 -0
- package/src/performance-profiler.ts +367 -0
- package/src/performance-sources.ts +69 -0
- package/src/play-boot-phase.ts +145 -0
- package/src/presentation-surface.ts +248 -0
- package/src/project-adapter.ts +1143 -0
- package/src/project-asset-refresh.ts +26 -0
- package/src/project-declaration-refresh.ts +31 -0
- package/src/project-local-state.ts +118 -0
- package/src/project-manager.ts +243 -0
- package/src/project-module-changes.ts +163 -0
- package/src/project-module-split.ts +266 -0
- package/src/project-provenance.ts +115 -0
- package/src/project-ready.ts +42 -0
- package/src/project-session-reset.ts +67 -0
- package/src/project-shape.ts +68 -0
- package/src/project-tool-discovery.ts +66 -0
- package/src/project-tools.ts +107 -0
- package/src/project-work-types.ts +149 -0
- package/src/projection/three.ts +898 -0
- package/src/projection/types.ts +44 -0
- package/src/readiness.ts +113 -0
- package/src/reflection-probe-helper.ts +142 -0
- package/src/reported-play-state.ts +90 -0
- package/src/resolve-relative-specifier.ts +33 -0
- package/src/scene-document-plan.ts +315 -0
- package/src/scene-framing.ts +315 -0
- package/src/scene-live-open.ts +210 -0
- package/src/scene-view-fog.ts +89 -0
- package/src/scoped-game-css.ts +152 -0
- package/src/session-orphan-record.ts +193 -0
- package/src/session-tombstone.ts +126 -0
- package/src/settings/settings-provider.ts +82 -0
- package/src/settings-store.ts +345 -0
- package/src/shared-view-restore.ts +42 -0
- package/src/shell-store-door.ts +45 -0
- package/src/source-conflict.ts +122 -0
- package/src/spatial-handle-visuals.ts +332 -0
- package/src/stage-context.ts +341 -0
- package/src/stage-store-registry.ts +63 -0
- package/src/stale-chunk-recovery.ts +34 -0
- package/src/state-report-deferral.ts +73 -0
- package/src/storage/host-files-storage.ts +97 -0
- package/src/storage/http-storage.ts +174 -0
- package/src/storage/index.ts +75 -0
- package/src/storage/mem-storage.ts +149 -0
- package/src/storage/path-lock.ts +44 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/types.ts +116 -0
- package/src/stories/StoryComponentThumbnail.tsx +184 -0
- package/src/stories/StoryPreviewMount.tsx +306 -0
- package/src/stories/component-content-source.tsx +106 -0
- package/src/stories/component-states-source.ts +78 -0
- package/src/stories/compose-project-stories.ts +255 -0
- package/src/stories/pixi-story-model.ts +30 -0
- package/src/stories/prefabs-finder.ts +54 -0
- package/src/stories/prefabs-from-stories.ts +182 -0
- package/src/stories/project-story-discovery.ts +78 -0
- package/src/stories/project-story-regions.ts +24 -0
- package/src/stories/story-actions.ts +54 -0
- package/src/stories/story-capture-command.ts +124 -0
- package/src/stories/story-capture.ts +584 -0
- package/src/stories/story-declared-medium.ts +126 -0
- package/src/stories/story-discovery.ts +176 -0
- package/src/stories/story-document-openers.ts +36 -0
- package/src/stories/story-dom-runtime.ts +78 -0
- package/src/stories/story-grouping.ts +111 -0
- package/src/stories/story-lane.ts +88 -0
- package/src/stories/story-mount-turn.ts +27 -0
- package/src/stories/story-opener.ts +260 -0
- package/src/stories/story-pixi-preview.ts +408 -0
- package/src/stories/story-presentation.ts +215 -0
- package/src/stories/story-registry.ts +517 -0
- package/src/stories/story-three-preview.ts +807 -0
- package/src/stories/three-story-model.ts +96 -0
- package/src/story-three-preview-runtime.ts +56 -0
- package/src/surface-keyboard.ts +112 -0
- package/src/surface-state.ts +124 -0
- package/src/tab-bootstrap.js +628 -0
- package/src/tab-census.ts +198 -0
- package/src/tab-lifecycle-client.ts +196 -0
- package/src/theme-library.ts +844 -0
- package/src/theme-preference.ts +378 -0
- package/src/theme.css +3437 -0
- package/src/three-viewport/bone-selection-highlight.ts +119 -0
- package/src/three-viewport/camera-fit.ts +41 -0
- package/src/three-viewport/interactive-renderer.ts +132 -0
- package/src/three-viewport/selection-brackets.ts +310 -0
- package/src/three-viewport/selection-outline.ts +183 -0
- package/src/three-viewport/skeleton-helper.ts +61 -0
- package/src/three-viewport/source-color.ts +167 -0
- package/src/three-viewport/studio-environment.ts +96 -0
- package/src/three-viewport-presentation.ts +23 -0
- package/src/tool-contribution-play.ts +74 -0
- package/src/tool-loader.ts +1798 -0
- package/src/transform-mode-request.ts +57 -0
- package/src/transient-hint.ts +78 -0
- package/src/trigger-volume-helper.ts +116 -0
- package/src/ui-source/adapter-region-includes.ts +241 -0
- package/src/ui-source/ensure-import.ts +132 -0
- package/src/ui-source/file-region-resolver.ts +302 -0
- package/src/ui-source/inspect.ts +775 -0
- package/src/ui-source/oid-transform.ts +1845 -0
- package/src/ui-source/plan-csf-story.ts +196 -0
- package/src/ui-source/plan-extract-component.ts +421 -0
- package/src/ui-source/plan-fork-component.ts +621 -0
- package/src/ui-source/plan-named-style.ts +95 -0
- package/src/ui-source/plan-source-edit.ts +353 -0
- package/src/ui-source/r3f-contract-resolver.ts +327 -0
- package/src/ui-source/r3f-diagnostic-index.ts +165 -0
- package/src/ui-source/r3f-environment-binding.ts +133 -0
- package/src/ui-source/r3f-joint-binding.ts +251 -0
- package/src/ui-source/r3f-lod-binding.ts +91 -0
- package/src/ui-source/r3f-particle-binding.ts +235 -0
- package/src/ui-source/r3f-physics-binding.ts +483 -0
- package/src/ui-source/r3f-project-contracts.ts +444 -0
- package/src/ui-source/relative-import-specifier.ts +34 -0
- package/src/ui-source/reparent-guard.ts +544 -0
- package/src/ui-source/source-edit-request.ts +97 -0
- package/src/ui-source/source-write-backend.ts +618 -0
- package/src/ui-source/syntactic-prop-specs.ts +296 -0
- package/src/ui-source/tier-source-write-backend.ts +279 -0
- package/src/ui-source/ts-ast.ts +171 -0
- package/src/ui-source/utility-class-support.ts +169 -0
- package/src/ui-source/write-component-default.ts +133 -0
- package/src/ui-source/writer.ts +1989 -0
- package/src/viewport-activation-timings.ts +840 -0
- package/src/viewport-authoring-policy.ts +186 -0
- package/src/viewport-controls-hint.ts +57 -0
- package/src/viewport-door.ts +237 -0
- package/src/viewport-shading-boundary.ts +12 -0
- package/src/vite-error-surface.ts +141 -0
- package/src/wait-until.ts +37 -0
- package/src/workspace-areas.ts +156 -0
- package/src/workspace-aux-commands.ts +11 -0
- package/src/workspace-available-documents.ts +127 -0
- package/src/workspace-core-utilities.ts +31 -0
- package/src/workspace-document-ids.ts +59 -0
- package/src/workspace-document-registry.ts +612 -0
- package/src/workspace-document-restore.ts +145 -0
- package/src/workspace-host-commands.ts +141 -0
- package/src/workspace-persistence-gate.ts +40 -0
- package/src/workspace-play-utilities.ts +44 -0
- package/src/workspace-presets.ts +425 -0
- package/src/workspace-regions.ts +294 -0
- package/src/workspace-state-persistence.ts +536 -0
- package/src/workspace-static-panels.ts +73 -0
- package/src/workspace-status-registry.ts +121 -0
- package/src/workspace-style.ts +239 -0
- package/src/workspace-utility-commands.ts +74 -0
- package/src/workspace-utility-registry.ts +263 -0
- package/src/workspace-viewport-rect.ts +97 -0
- package/src/world-adoption.ts +115 -0
- package/src/world-document-routing.ts +104 -0
- package/vite-plugin-creation-site-write.ts +184 -0
- package/vite-plugin-creation-site.ts +80 -0
- package/vite-plugin-game-static.ts +303 -0
- package/vite-plugin-module-doorways.ts +336 -0
- package/vite-plugin-product-contributions.ts +197 -0
- package/vite-plugin-project-game-static.ts +125 -0
- package/vite-plugin-project-jsx-js.ts +65 -0
- package/vite-plugin-project-root-absolute-assets.ts +359 -0
- package/vite-plugin-shared-react.ts +420 -0
- package/vite-plugin-shared-three.ts +203 -0
- package/vite-plugin-ui-oid.ts +2106 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reading and writing the project's own files.
|
|
3
|
+
*
|
|
4
|
+
* `public/` operations route through the backend-agnostic `StorageBackend`
|
|
5
|
+
* (`../storage`): `HttpStorage` over the same `/__editor/*` routes, wrapped by
|
|
6
|
+
* the frame's file door once its provider lands.
|
|
7
|
+
*
|
|
8
|
+
* The SPA-fallback check here is load-bearing: a dev server answers 200 with
|
|
9
|
+
* the editor's own `index.html` for a missing file, so "did I get the file"
|
|
10
|
+
* cannot be asked of the status code alone.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { resolveUrl } from '@volter/editor-threejs/loader';
|
|
14
|
+
import { base64ToBytes } from '../bytes-codec';
|
|
15
|
+
import { getStorageBackend } from '../storage';
|
|
16
|
+
/**
|
|
17
|
+
* Read a project text file from the session that owns the project namespace.
|
|
18
|
+
*
|
|
19
|
+
* The storage backend is NOT the door here: `HttpStorage` is rooted at
|
|
20
|
+
* `public/`, not at the project root, so asking it for `src/...` produces a
|
|
21
|
+
* known-false asset-list 404 before the real Vite read. This goes directly to
|
|
22
|
+
* HTTP. Returns null when the file is not served.
|
|
23
|
+
*/
|
|
24
|
+
export async function readProjectTextFile(path: string): Promise<string | null> {
|
|
25
|
+
try {
|
|
26
|
+
const res = await fetch(resolveUrl(path));
|
|
27
|
+
if (res.ok) return await res.text();
|
|
28
|
+
} catch {
|
|
29
|
+
/* ignore */
|
|
30
|
+
}
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* What a probe can honestly conclude about a project file. THREE answers,
|
|
36
|
+
* because "no" and "I could not tell" are different facts and a boolean has
|
|
37
|
+
* to spend one of them.
|
|
38
|
+
*/
|
|
39
|
+
export type ProjectFilePresence = 'present' | 'absent' | 'unreachable';
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A 200 that is really the SPA FALLBACK, not the file.
|
|
43
|
+
*
|
|
44
|
+
* MEASURED, dev server, project root `public/ingest/cuberun/` (which owns no
|
|
45
|
+
* `vgai.adapter.ts`):
|
|
46
|
+
*
|
|
47
|
+
* curl -sI /vgai.adapter.ts -> 200, Content-Type: text/html (index.html)
|
|
48
|
+
* curl -sI /vgai.project.json -> 200, Content-Type: application/json; charset=utf-8
|
|
49
|
+
*
|
|
50
|
+
* The fallback serves the editor's own `index.html`, so it is identifiable by
|
|
51
|
+
* the one thing it cannot hide: it is an HTML DOCUMENT. Nothing this probe is
|
|
52
|
+
* ever pointed at — a module, a manifest, an asset — is served as `text/html`,
|
|
53
|
+
* and the storage backend answers first for anything that could be.
|
|
54
|
+
*
|
|
55
|
+
* This shape is not dev-only: `docs/DEPLOY.md` §Surface 3 specifies serving
|
|
56
|
+
* `dist/` with an index.html fallback, i.e. "a missing asset returns
|
|
57
|
+
* `index.html`". Both shipped surfaces answer the same way.
|
|
58
|
+
*/
|
|
59
|
+
function isSpaFallbackDocument(response: Response): boolean {
|
|
60
|
+
return (response.headers.get('content-type') ?? '').toLowerCase().includes('text/html');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Does this project file exist? — CONTENT-DISCRIMINATED, because on both
|
|
65
|
+
* surfaces this product ships an existence probe that trusts `res.ok` is a
|
|
66
|
+
* constant `true`.
|
|
67
|
+
*
|
|
68
|
+
* `HttpStorage` is deliberately rooted at
|
|
69
|
+
* `public/`, while this probe accepts project-root paths such as
|
|
70
|
+
* `src/prefabs/Player.tsx`; asking that backend first turns an ordinary source
|
|
71
|
+
* probe into a noisy `/__editor/assets?dir=src` 404. This therefore
|
|
72
|
+
* asks Vite directly with HEAD. Both routes remain existence-only — neither
|
|
73
|
+
* downloads the file body.
|
|
74
|
+
*
|
|
75
|
+
* The HTTP probe classifies rather than trusting `res.ok`:
|
|
76
|
+
*
|
|
77
|
+
* - not ok -> `absent` (a real 404 from a real route);
|
|
78
|
+
* - ok + `text/html` -> `absent` — {@link isSpaFallbackDocument}, the
|
|
79
|
+
* measured false positive;
|
|
80
|
+
* - ok, anything else -> `present` (a real file answering with its own
|
|
81
|
+
* content type);
|
|
82
|
+
* - the fetch throws -> `unreachable`. NOT `absent`: an unanswered probe is
|
|
83
|
+
* a fact about the transport, and a caller that must not act on a guess
|
|
84
|
+
* (see `project-adapter.ts`, which chooses a BINDING TABLE off this) is
|
|
85
|
+
* entitled to know the difference.
|
|
86
|
+
*
|
|
87
|
+
* This function's earlier docblock already recorded the false positive —
|
|
88
|
+
* "the dev server's SPA fallback also answers a HEAD/GET for a MISSING path
|
|
89
|
+
* with 200 (it serves `index.html` rather than 404), so `res.ok` alone cannot
|
|
90
|
+
* fully distinguish 'exists' from 'missing'" — and dismissed it as harmless
|
|
91
|
+
* because "a false positive here just means a subsequent real open attempt
|
|
92
|
+
* fails through its own error path". That held for the then-only caller
|
|
93
|
+
* (`workspace-state-persistence`, probing `public/`-rooted asset paths the
|
|
94
|
+
* storage backend answers authoritatively). It stopped holding the moment a
|
|
95
|
+
* project-ROOT path was probed AHEAD of a branch that would otherwise have
|
|
96
|
+
* succeeded: the "own error path" then reports a load failure for a file the
|
|
97
|
+
* project never had, and the real binding is never reached. The discrimination
|
|
98
|
+
* lives HERE, inside the probe, so the next caller cannot re-inherit the blind
|
|
99
|
+
* question.
|
|
100
|
+
*/
|
|
101
|
+
export async function probeProjectFile(path: string): Promise<ProjectFilePresence> {
|
|
102
|
+
// Ask the origin; the fallback detector below keeps a SPA 200 from counting
|
|
103
|
+
// as the file.
|
|
104
|
+
try {
|
|
105
|
+
const res = await fetch(resolveUrl(path), { method: 'HEAD' });
|
|
106
|
+
if (!res.ok) return 'absent';
|
|
107
|
+
return isSpaFallbackDocument(res) ? 'absent' : 'present';
|
|
108
|
+
} catch {
|
|
109
|
+
return 'unreachable';
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Check whether a project file exists WITHOUT reading its content — the
|
|
115
|
+
* boolean face of {@link probeProjectFile}, for callers with nothing to do
|
|
116
|
+
* about the difference between "no" and "could not tell". Prefer this over
|
|
117
|
+
* `readProjectTextFile(...) !== null` when only existence is needed, since
|
|
118
|
+
* that reads and discards the whole body.
|
|
119
|
+
*/
|
|
120
|
+
export async function projectFileExists(path: string): Promise<boolean> {
|
|
121
|
+
return (await probeProjectFile(path)) === 'present';
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Save a file to public/. Returns true on success. */
|
|
125
|
+
export async function saveFile(
|
|
126
|
+
path: string,
|
|
127
|
+
content: string,
|
|
128
|
+
encoding?: 'base64',
|
|
129
|
+
): Promise<boolean> {
|
|
130
|
+
try {
|
|
131
|
+
// base64 content → raw bytes; the backend re-encodes per its transport.
|
|
132
|
+
// `base64ToBytes` is a LOOP; `Uint8Array.from(atob(…), (c) => …)` calls the
|
|
133
|
+
// mapping callback once per CHARACTER (measured 27.7x slower at 3MB).
|
|
134
|
+
const data: string | Uint8Array = encoding === 'base64' ? base64ToBytes(content) : content;
|
|
135
|
+
await getStorageBackend().write(path, data);
|
|
136
|
+
return true;
|
|
137
|
+
} catch {
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Project-relative source files matching `globs` (`src/models/**\/*.ts`; `*`
|
|
144
|
+
* within a segment, `**` across segments) — what a finder's `include`
|
|
145
|
+
* reads through (`FinderInput.sources`), answered by the session's
|
|
146
|
+
* `/__editor/source-files` route.
|
|
147
|
+
*/
|
|
148
|
+
export async function listProjectSourceFiles(
|
|
149
|
+
globs: readonly string[],
|
|
150
|
+
options: { readonly order?: 'name' | 'mtime' } = {},
|
|
151
|
+
): Promise<string[]> {
|
|
152
|
+
if (globs.length === 0) return [];
|
|
153
|
+
const res = await fetch(
|
|
154
|
+
`/__editor/source-files?${new URLSearchParams([
|
|
155
|
+
...globs.map((g): [string, string] => ['include', g]),
|
|
156
|
+
...(options.order === 'mtime' ? [['order', 'mtime'] as [string, string]] : []),
|
|
157
|
+
])}`,
|
|
158
|
+
);
|
|
159
|
+
if (!res.ok) return [];
|
|
160
|
+
const body = (await res.json()) as { files?: string[] };
|
|
161
|
+
return body.files ?? [];
|
|
162
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the session currently IS, as the editor's own UI reads it: the server
|
|
3
|
+
* validation log, the editor lease identity, and the durable
|
|
4
|
+
* `.vgai/editor-state.json` view/tool state.
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { LeasePollResult } from '../editor-lease';
|
|
9
|
+
import { assertEditorServerResponse, editorServerJson } from '../editor-server-response';
|
|
10
|
+
import { BASE } from './base';
|
|
11
|
+
/**
|
|
12
|
+
* PD-13: the validation failures and authoring warnings the dev server knows
|
|
13
|
+
* about RIGHT NOW, pre-formatted as `server-log` payloads. `editor-console.ts`
|
|
14
|
+
* pulls this once per connection to render what the live broadcast could not
|
|
15
|
+
* deliver — see `connectServerLogs` for why a pull rather than a push. THROWS
|
|
16
|
+
* on any failure, including a server that predates the endpoint and an origin
|
|
17
|
+
* whose page fallback answered instead; the one caller treats a failed replay
|
|
18
|
+
* as "nothing to replay" and says why.
|
|
19
|
+
*/
|
|
20
|
+
export async function getServerValidationLog(): Promise<{ level: string; message: string }[]> {
|
|
21
|
+
const res = await fetch(`${BASE}/validation-log`);
|
|
22
|
+
const data = await editorServerJson<{ entries?: { level: string; message: string }[] }>(
|
|
23
|
+
res,
|
|
24
|
+
'Could not read the server validation log',
|
|
25
|
+
);
|
|
26
|
+
return data.entries ?? [];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* One liveness poll for the editor-lease watchdog (editor-lease.ts): ask the
|
|
31
|
+
* server on THIS tab's origin who it is. Reuses the same `/__editor/project`
|
|
32
|
+
* identity endpoint the CLI probes (`session.pid` + the served project path) —
|
|
33
|
+
* a replaced server on the same port answers with a new pid, which is how the
|
|
34
|
+
* watchdog detects a takeover.
|
|
35
|
+
*
|
|
36
|
+
* `ok: false` is any reason the reading is unusable — connection refused (the
|
|
37
|
+
* server is gone), a non-OK status, a timeout, or a malformed body — folded
|
|
38
|
+
* into one "failed poll" the reducer counts toward `server-gone`. The timeout
|
|
39
|
+
* is short: this runs every few seconds and a hung request should read as a
|
|
40
|
+
* failure, not stall the poll.
|
|
41
|
+
*/
|
|
42
|
+
export async function pollEditorLeaseIdentity(timeoutMs = 3000): Promise<LeasePollResult> {
|
|
43
|
+
// Browser mode has no Node server to lease from; the watchdog never mounts
|
|
44
|
+
// there, but guard anyway so a stray call can never false-void a page.
|
|
45
|
+
if (typeof fetch === 'undefined') return { ok: false };
|
|
46
|
+
try {
|
|
47
|
+
const res = await fetch(`${BASE}/project`, { signal: AbortSignal.timeout(timeoutMs) });
|
|
48
|
+
const body = await editorServerJson<{
|
|
49
|
+
project?: { path?: unknown } | null;
|
|
50
|
+
session?: { pid?: unknown } | null;
|
|
51
|
+
}>(res, 'Editor lease poll failed');
|
|
52
|
+
return {
|
|
53
|
+
ok: true,
|
|
54
|
+
identity: {
|
|
55
|
+
project: typeof body.project?.path === 'string' ? body.project.path : null,
|
|
56
|
+
pid: typeof body.session?.pid === 'number' ? body.session.pid : null,
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
} catch {
|
|
60
|
+
return { ok: false };
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------------
|
|
65
|
+
// Persistent editor state (.vgai/editor-state.json)
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
/** Load persisted editor state (remembered transform mode/snap/last
|
|
69
|
+
* scene/camera). Returns {} if none exists. */
|
|
70
|
+
export async function loadEditorState(): Promise<Record<string, unknown>> {
|
|
71
|
+
try {
|
|
72
|
+
const res = await fetch(`${BASE}/editor-state`);
|
|
73
|
+
return await editorServerJson<Record<string, unknown>>(res, 'Could not read editor state');
|
|
74
|
+
} catch {
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** Set once the write below has reported a failure, so an autosave that fires
|
|
80
|
+
* on every viewport change reports a permanently broken origin ONCE. */
|
|
81
|
+
let reportedEditorStateWriteFailure = false;
|
|
82
|
+
|
|
83
|
+
/** Save editor state (persisted in .vgai/editor-state.json — see
|
|
84
|
+
* `loadEditorState`'s doc comment for the browser-mode routing).
|
|
85
|
+
*
|
|
86
|
+
* The boolean is this function's only channel and its one caller
|
|
87
|
+
* (`editor-shell-store.savePersistentState`) discards it, so the failure is
|
|
88
|
+
* ALSO logged: `res.ok` used to read a page fallback as a completed write,
|
|
89
|
+
* and a silent false would be the same lie one indirection later. */
|
|
90
|
+
export async function saveEditorState(state: Record<string, unknown>): Promise<boolean> {
|
|
91
|
+
try {
|
|
92
|
+
const res = await fetch(`${BASE}/editor-state`, {
|
|
93
|
+
method: 'POST',
|
|
94
|
+
headers: { 'Content-Type': 'application/json' },
|
|
95
|
+
body: JSON.stringify(state),
|
|
96
|
+
});
|
|
97
|
+
assertEditorServerResponse(res, 'Could not save editor state');
|
|
98
|
+
return true;
|
|
99
|
+
} catch (cause) {
|
|
100
|
+
if (!reportedEditorStateWriteFailure) {
|
|
101
|
+
reportedEditorStateWriteFailure = true;
|
|
102
|
+
// biome-ignore lint/suspicious/noConsole: the editor console captures console.error session-wide — this IS the report channel for a caller that discards the boolean.
|
|
103
|
+
console.error(cause instanceof Error ? cause.message : String(cause));
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
package/src/api/relay.ts
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a TAB reports upstream: its state snapshot, that it picked a command
|
|
3
|
+
* up, that a command finished, which play-boot phase it is in — plus the
|
|
4
|
+
* gameplay recording sink.
|
|
5
|
+
*
|
|
6
|
+
* The editor-state reporter serializes and coalesces on purpose. One user
|
|
7
|
+
* action can change several things at once (a Play click changes both play
|
|
8
|
+
* state and the active viewport), so only the newest waiting snapshot is kept
|
|
9
|
+
* and sends are serialized — an older, slower report can never land after a
|
|
10
|
+
* newer one and roll `/__editor/state` back.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import {
|
|
14
|
+
EDITOR_CLIENT_ID,
|
|
15
|
+
reportTabPhase,
|
|
16
|
+
sendCommandResultControl,
|
|
17
|
+
sendControl,
|
|
18
|
+
} from '../editor-presence';
|
|
19
|
+
import { assertEditorServerAnswered } from '../editor-server-response';
|
|
20
|
+
import { BASE } from './base';
|
|
21
|
+
|
|
22
|
+
// State reports can be triggered by several browser-owned transitions at once
|
|
23
|
+
// (a Play click changes both play state and the active viewport, for example).
|
|
24
|
+
// Keep only the newest waiting snapshot and serialize sends so an older,
|
|
25
|
+
// slower report can never land after a newer one and roll `/__editor/state`
|
|
26
|
+
// back.
|
|
27
|
+
let pendingEditorState: Record<string, unknown> | null = null;
|
|
28
|
+
let editorStateReportDrain: Promise<void> | null = null;
|
|
29
|
+
|
|
30
|
+
async function drainEditorStateReports(): Promise<void> {
|
|
31
|
+
while (pendingEditorState) {
|
|
32
|
+
const state = pendingEditorState;
|
|
33
|
+
pendingEditorState = null;
|
|
34
|
+
await sendControl('state', { ...state, _clientId: EDITOR_CLIENT_ID });
|
|
35
|
+
}
|
|
36
|
+
editorStateReportDrain = null;
|
|
37
|
+
// A caller cannot interleave with the synchronous block above, but keep
|
|
38
|
+
// this defensive restart so future refactors cannot strand a late report.
|
|
39
|
+
if (pendingEditorState) editorStateReportDrain = drainEditorStateReports();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Report the current editor state to the server (called by command-listener). */
|
|
43
|
+
export function reportEditorState(state: Record<string, unknown>): Promise<void> {
|
|
44
|
+
pendingEditorState = state;
|
|
45
|
+
editorStateReportDrain ??= drainEditorStateReports();
|
|
46
|
+
return editorStateReportDrain;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tell the server this tab PICKED UP a relayed command — sent before the work
|
|
51
|
+
* starts, so it says "my command listener is running", nothing about the
|
|
52
|
+
* outcome.
|
|
53
|
+
*
|
|
54
|
+
* Long-budget commands (`play` waits out a whole async `setup()`) used to give
|
|
55
|
+
* a tab that had stopped answering the control channel the same silence as a tab
|
|
56
|
+
* that was merely busy, and the caller waited the entire budget for a result
|
|
57
|
+
* that was never coming. This receipt is what separates the two — see
|
|
58
|
+
* `server/server-utils.ts`'s `RELAY_DELIVERY_ACK_MS`. Best-effort and
|
|
59
|
+
* deliberately not awaited by the caller: a lost receipt costs a fast, named
|
|
60
|
+
* refusal, never a wrong result.
|
|
61
|
+
*/
|
|
62
|
+
export async function reportCommandReceived(requestId: string): Promise<void> {
|
|
63
|
+
await sendControl('command-received', { _requestId: requestId, _clientId: EDITOR_CLIENT_ID });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Tell the server whether this page is RUNNING a command listener at all.
|
|
68
|
+
*
|
|
69
|
+
* The receipt above answers that question one command at a time, and only
|
|
70
|
+
* after somebody sends a command. This answers it standing, at the two moments
|
|
71
|
+
* that change the answer — `connectCommandListener` attaching, and its
|
|
72
|
+
* teardown running — so `vgai status` can name a dead page on the FIRST read
|
|
73
|
+
* instead of it being inferable only from a command that hangs.
|
|
74
|
+
*
|
|
75
|
+
* It is worth its own message because presence cannot carry it: the control
|
|
76
|
+
* channel is opened by the tiny pre-React entry
|
|
77
|
+
* (`early-editor-presence.ts`), long before the React graph that owns the
|
|
78
|
+
* listener finishes loading — so a page that dies in between connects,
|
|
79
|
+
* beats, and executes nothing.
|
|
80
|
+
*/
|
|
81
|
+
export async function reportCommandListener(attached: boolean): Promise<void> {
|
|
82
|
+
await sendControl('command-listener', { _clientId: EDITOR_CLIENT_ID, attached });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Tell the server which play-boot step this page is ENTERING.
|
|
87
|
+
*
|
|
88
|
+
* Sent before the step's work, never after it, so a step that never returns is
|
|
89
|
+
* still named — see `play-boot-phase.ts` for the 199.5-second block that made
|
|
90
|
+
* three consecutive commands time out against a session every reader called
|
|
91
|
+
* healthy. Not awaited by the caller: the phase is diagnostics, and diagnostics
|
|
92
|
+
* that can delay a boot are worse than none.
|
|
93
|
+
*/
|
|
94
|
+
export function reportPlayBootPhase(state: {
|
|
95
|
+
phase: string | null;
|
|
96
|
+
at: number;
|
|
97
|
+
run: number;
|
|
98
|
+
}): void {
|
|
99
|
+
// Two roads, because the control socket is the PAGE's: a phase announced
|
|
100
|
+
// right before a synchronous block sat in the page's send queue until the
|
|
101
|
+
// block ended (measured 2026-09-06: a 45 s build's phase arrived after the
|
|
102
|
+
// build). The heartbeat worker's socket keeps beating through the block,
|
|
103
|
+
// so the phase rides the next beat too; whichever lands first wins.
|
|
104
|
+
reportTabPhase(state.phase);
|
|
105
|
+
void sendControl('play-phase', { _clientId: EDITOR_CLIENT_ID, ...state });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** Report a command result back to the server so the SDK/CLI gets the response.
|
|
109
|
+
* `data` carries an optional payload for commands that answer with data
|
|
110
|
+
* (e.g. `capture-viewport`'s base64 PNG, the debug-seam reads)
|
|
111
|
+
* forwarded verbatim through `/__editor/command-result` →
|
|
112
|
+
* `commandResponseFor` → the SDK transports, on the failure path too (where
|
|
113
|
+
* it carries structured `{ code: ... }` markers). */
|
|
114
|
+
export async function reportCommandResult(
|
|
115
|
+
requestId: string,
|
|
116
|
+
ok: boolean,
|
|
117
|
+
error?: string,
|
|
118
|
+
data?: Record<string, unknown>,
|
|
119
|
+
waitForCaller = false,
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
const payload = {
|
|
122
|
+
_requestId: requestId,
|
|
123
|
+
_clientId: EDITOR_CLIENT_ID,
|
|
124
|
+
ok,
|
|
125
|
+
error,
|
|
126
|
+
data,
|
|
127
|
+
};
|
|
128
|
+
if (waitForCaller) await sendCommandResultControl(requestId, payload);
|
|
129
|
+
else await sendControl('command-result', payload);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface GameplayRecordingSink {
|
|
133
|
+
id: string;
|
|
134
|
+
path: string;
|
|
135
|
+
format: 'composite-webm' | 'canvas-dom';
|
|
136
|
+
/** Directory containing `manifest.json`, `events.json`, and interned assets
|
|
137
|
+
* for a canvas + DOM recording. Absent for a composite WebM. */
|
|
138
|
+
replayPath: string | null;
|
|
139
|
+
/** True when this sink is the ROTATING unnamed file — the next recording
|
|
140
|
+
* overwrites it. False for a caller-named keepsake. */
|
|
141
|
+
rotates: boolean;
|
|
142
|
+
/** The `logs/play-*.jsonl` this project's live play run is writing, or
|
|
143
|
+
* `null` when nothing is logging. Its event timestamps are what map an
|
|
144
|
+
* event to an offset in the clip, so it travels WITH the clip's identity
|
|
145
|
+
* rather than being looked up separately later. */
|
|
146
|
+
logFile: string | null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
async function recordingResponse<T>(response: Response, action: string): Promise<T> {
|
|
150
|
+
// `.json().catch(() => ({}))` under a page fallback produced an OK-looking
|
|
151
|
+
// empty sink: `start` handed back a sink with no id, and every chunk after it
|
|
152
|
+
// posted into nothing while the recorder showed a recording in progress.
|
|
153
|
+
assertEditorServerAnswered(response, `gameplay recording ${action} failed`);
|
|
154
|
+
const body = (await response.json().catch(() => ({}))) as { error?: unknown } & T;
|
|
155
|
+
if (!response.ok) {
|
|
156
|
+
throw new Error(
|
|
157
|
+
`gameplay recording ${action} failed: ${typeof body.error === 'string' ? body.error : `HTTP ${response.status}`}`,
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
return body;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Open the server-owned, project-scoped WebM sink. Video bytes never ride the
|
|
164
|
+
* JSON command relay: a long QA playthrough must not hit its 50 MiB ceiling. */
|
|
165
|
+
export async function beginGameplayRecordingSink(
|
|
166
|
+
input: {
|
|
167
|
+
startedAt: string;
|
|
168
|
+
mimeType: string;
|
|
169
|
+
format?: 'composite-webm' | 'canvas-dom';
|
|
170
|
+
/** Fixed-step exports do not use the session's wall-clock playback timeline. */
|
|
171
|
+
purpose?: 'export';
|
|
172
|
+
/** During Play, `null` names the clip after the Gameplay Session; outside
|
|
173
|
+
* one it falls back to `play-latest.webm`. A name takes a keepsake path. */
|
|
174
|
+
name?: string | null;
|
|
175
|
+
},
|
|
176
|
+
signal?: AbortSignal,
|
|
177
|
+
): Promise<GameplayRecordingSink> {
|
|
178
|
+
const response = await fetch(`${BASE}/recording/start`, {
|
|
179
|
+
...(signal ? { signal } : {}),
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: { 'content-type': 'application/json' },
|
|
182
|
+
body: JSON.stringify(input),
|
|
183
|
+
});
|
|
184
|
+
return recordingResponse<GameplayRecordingSink>(response, 'start');
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/** Append an ordered batch of standard rrweb events. */
|
|
188
|
+
export async function appendGameplayRecordingDomEvents(
|
|
189
|
+
sink: GameplayRecordingSink,
|
|
190
|
+
sequence: number,
|
|
191
|
+
eventsJson: Blob,
|
|
192
|
+
signal?: AbortSignal,
|
|
193
|
+
): Promise<void> {
|
|
194
|
+
const query = new URLSearchParams({ id: sink.id, sequence: String(sequence) });
|
|
195
|
+
const response = await fetch(`${BASE}/recording/dom?${query}`, {
|
|
196
|
+
...(signal ? { signal } : {}),
|
|
197
|
+
method: 'POST',
|
|
198
|
+
// This is a streamed file body. Labeling it application/json lets the
|
|
199
|
+
// server's ordinary JSON middleware consume it before the route can apply
|
|
200
|
+
// its own byte bound, ordering, and append semantics.
|
|
201
|
+
headers: { 'content-type': 'application/octet-stream' },
|
|
202
|
+
body: eventsJson,
|
|
203
|
+
});
|
|
204
|
+
await recordingResponse<Record<string, never>>(response, 'DOM event upload');
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** Store one image interned out of the rrweb event stream. */
|
|
208
|
+
export async function appendGameplayRecordingAsset(
|
|
209
|
+
sink: GameplayRecordingSink,
|
|
210
|
+
name: string,
|
|
211
|
+
asset: Blob,
|
|
212
|
+
signal?: AbortSignal,
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
const query = new URLSearchParams({ id: sink.id, name });
|
|
215
|
+
const response = await fetch(`${BASE}/recording/asset?${query}`, {
|
|
216
|
+
...(signal ? { signal } : {}),
|
|
217
|
+
method: 'POST',
|
|
218
|
+
headers: { 'content-type': asset.type || 'application/octet-stream' },
|
|
219
|
+
body: asset,
|
|
220
|
+
});
|
|
221
|
+
await recordingResponse<Record<string, never>>(response, 'replay asset upload');
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Append one ordered MediaRecorder chunk to the open WebM. */
|
|
225
|
+
export async function appendGameplayRecordingChunk(
|
|
226
|
+
sink: GameplayRecordingSink,
|
|
227
|
+
sequence: number,
|
|
228
|
+
chunk: Blob,
|
|
229
|
+
signal?: AbortSignal,
|
|
230
|
+
): Promise<void> {
|
|
231
|
+
const query = new URLSearchParams({ id: sink.id, sequence: String(sequence) });
|
|
232
|
+
const response = await fetch(`${BASE}/recording/chunk?${query}`, {
|
|
233
|
+
...(signal ? { signal } : {}),
|
|
234
|
+
method: 'POST',
|
|
235
|
+
headers: { 'content-type': 'application/octet-stream' },
|
|
236
|
+
body: chunk,
|
|
237
|
+
});
|
|
238
|
+
await recordingResponse<Record<string, never>>(response, 'chunk upload');
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export async function finishGameplayRecordingSink(
|
|
242
|
+
sink: GameplayRecordingSink,
|
|
243
|
+
/** What ended it — journalled verbatim beside the file it produced. */
|
|
244
|
+
reason?: string | null,
|
|
245
|
+
signal?: AbortSignal,
|
|
246
|
+
replay?: Record<string, unknown> | null,
|
|
247
|
+
): Promise<void> {
|
|
248
|
+
const response = await fetch(`${BASE}/recording/finish`, {
|
|
249
|
+
...(signal ? { signal } : {}),
|
|
250
|
+
method: 'POST',
|
|
251
|
+
headers: { 'content-type': 'application/json' },
|
|
252
|
+
body: JSON.stringify({ id: sink.id, reason: reason ?? null, replay: replay ?? null }),
|
|
253
|
+
});
|
|
254
|
+
await recordingResponse<Record<string, never>>(response, 'finish');
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/** Deliberately NOT read through `editor-server-response.ts`: this is the
|
|
258
|
+
* teardown leg, called only when a recording is already being abandoned, and
|
|
259
|
+
* its `.catch(() => undefined)` is the contract — there is no caller left to
|
|
260
|
+
* report to, so asserting could only turn a silent no-op into a swallowed
|
|
261
|
+
* throw. */
|
|
262
|
+
export async function abortGameplayRecordingSink(sink: GameplayRecordingSink): Promise<void> {
|
|
263
|
+
await fetch(`${BASE}/recording/abort`, {
|
|
264
|
+
method: 'POST',
|
|
265
|
+
headers: { 'content-type': 'application/json' },
|
|
266
|
+
body: JSON.stringify({ id: sink.id }),
|
|
267
|
+
}).catch(() => undefined);
|
|
268
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two shared settings layers over the wire (`server/routes/settings.ts`):
|
|
3
|
+
* `~/.vgai/settings.json` (user) and `<project>/.vgai/settings.json`
|
|
4
|
+
* (project), both files the editor server owns.
|
|
5
|
+
*/
|
|
6
|
+
import type { EditorSettings } from '@volter/editor-project/settings/schema';
|
|
7
|
+
import { assertEditorServerResponse, editorServerJson } from '../editor-server-response';
|
|
8
|
+
import { BASE } from './base';
|
|
9
|
+
|
|
10
|
+
export type SettingsLayer = 'user' | 'project';
|
|
11
|
+
|
|
12
|
+
export interface SettingsLayerRead {
|
|
13
|
+
readonly settings: EditorSettings;
|
|
14
|
+
/** Problems with the stored document, spelled for the person who owns it. */
|
|
15
|
+
readonly issues: readonly string[];
|
|
16
|
+
/** Where the layer lives, for the issue report. */
|
|
17
|
+
readonly path: string | null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function loadSettingsLayer(layer: SettingsLayer): Promise<SettingsLayerRead> {
|
|
21
|
+
const res = await fetch(`${BASE}/settings/${layer}`);
|
|
22
|
+
return editorServerJson<SettingsLayerRead>(res, `Could not read ${layer} settings`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function saveSettingsLayer(
|
|
26
|
+
layer: SettingsLayer,
|
|
27
|
+
settings: EditorSettings,
|
|
28
|
+
): Promise<void> {
|
|
29
|
+
const body = JSON.stringify(settings, null, 2);
|
|
30
|
+
const res = await fetch(`${BASE}/settings/${layer}`, {
|
|
31
|
+
method: 'POST',
|
|
32
|
+
headers: { 'Content-Type': 'application/json' },
|
|
33
|
+
body,
|
|
34
|
+
});
|
|
35
|
+
assertEditorServerResponse(res, `Could not save ${layer} settings`);
|
|
36
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom palette documents over the wire (`server/routes/themes.ts`): one
|
|
3
|
+
* JSON file per theme under `~/.vgai/themes/` (user) and
|
|
4
|
+
* `<project>/.vgai/themes/` (project) — both files the editor server owns.
|
|
5
|
+
*/
|
|
6
|
+
import { assertEditorServerResponse, editorServerJson } from '../editor-server-response';
|
|
7
|
+
import { BASE } from './base';
|
|
8
|
+
import type { SettingsLayer } from './settings';
|
|
9
|
+
|
|
10
|
+
export interface ThemeDocumentRead {
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly path: string;
|
|
13
|
+
readonly document: unknown;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ThemeLayerRead {
|
|
17
|
+
readonly documents: readonly ThemeDocumentRead[];
|
|
18
|
+
/** Files that could not be read as JSON, spelled by path. */
|
|
19
|
+
readonly issues: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export async function listThemeDocuments(layer: SettingsLayer): Promise<ThemeLayerRead> {
|
|
23
|
+
const res = await fetch(`${BASE}/themes/${layer}`);
|
|
24
|
+
return editorServerJson<ThemeLayerRead>(res, `Could not list ${layer} themes`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export async function saveThemeDocument(
|
|
28
|
+
layer: SettingsLayer,
|
|
29
|
+
id: string,
|
|
30
|
+
document: unknown,
|
|
31
|
+
): Promise<void> {
|
|
32
|
+
const res = await fetch(`${BASE}/themes/${layer}`, {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
headers: { 'Content-Type': 'application/json' },
|
|
35
|
+
body: JSON.stringify({ id, document }),
|
|
36
|
+
});
|
|
37
|
+
assertEditorServerResponse(res, `Could not save the ${layer} theme ${id}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function deleteThemeDocument(layer: SettingsLayer, id: string): Promise<void> {
|
|
41
|
+
const res = await fetch(`${BASE}/themes/${layer}?id=${encodeURIComponent(id)}`, {
|
|
42
|
+
method: 'DELETE',
|
|
43
|
+
});
|
|
44
|
+
assertEditorServerResponse(res, `Could not delete the ${layer} theme ${id}`);
|
|
45
|
+
}
|