@volter/sdk 0.0.0-stage → 0.5.204
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/LICENSE +202 -0
- package/NOTICE +20 -0
- package/README.md +38 -3
- package/package.json +510 -4
- package/src/account.ts +210 -0
- package/src/chrome.ts +88 -0
- package/src/client.ts +1646 -0
- package/src/commands.ts +66 -0
- package/src/contributions.ts +619 -0
- package/src/css-numeric-style.ts +97 -0
- package/src/document-probe.ts +282 -0
- package/src/editor-view.ts +225 -0
- package/src/extension.ts +40 -0
- package/src/generations.ts +178 -0
- package/src/host.ts +1157 -0
- package/src/http-transport.browser.ts +14 -0
- package/src/http-transport.node.ts +19 -0
- package/src/index.ts +131 -0
- package/src/kit/CapabilityCoverageSection.tsx +185 -0
- package/src/kit/account-client.ts +333 -0
- package/src/kit/action-registry.ts +317 -0
- package/src/kit/active-product.ts +76 -0
- package/src/kit/active-project.ts +155 -0
- package/src/kit/adapter-editor-config.ts +25 -0
- package/src/kit/adapter-module.ts +7 -0
- package/src/kit/adapter-observation.ts +49 -0
- package/src/kit/animation/animation-clock.ts +479 -0
- package/src/kit/animation/stage-transport.ts +385 -0
- package/src/kit/api/assets.ts +365 -0
- package/src/kit/api/project-open.ts +355 -0
- package/src/kit/api/project-source.ts +180 -0
- package/src/kit/api/project-state.ts +110 -0
- package/src/kit/api/relay.ts +270 -0
- package/src/kit/api/themes.ts +45 -0
- package/src/kit/api-asset-library-wire.ts +45 -0
- package/src/kit/api-base.ts +10 -0
- package/src/kit/api-build.ts +99 -0
- package/src/kit/api-git-wire.ts +56 -0
- package/src/kit/api-logs.ts +92 -0
- package/src/kit/api-project-identity.ts +74 -0
- package/src/kit/api-settings.ts +36 -0
- package/src/kit/api-worktrees.ts +205 -0
- package/src/kit/asset-capabilities.ts +344 -0
- package/src/kit/asset-compare-core.ts +171 -0
- package/src/kit/asset-editor-context.tsx +101 -0
- package/src/kit/asset-events.ts +96 -0
- package/src/kit/asset-inspector-actions.ts +87 -0
- package/src/kit/asset-selection-viewer-registry.ts +113 -0
- package/src/kit/asset-selection.ts +146 -0
- package/src/kit/asset-thumbnails.ts +25 -0
- package/src/kit/asset-viewers.ts +115 -0
- package/src/kit/asset-workflow/asset-import-jobs.ts +106 -0
- package/src/kit/asset-workflow/asset-ledger-backend.ts +126 -0
- package/src/kit/asset-workflow/asset-ledger.ts +156 -0
- package/src/kit/asset-workflow/asset-materialization-report.ts +140 -0
- package/src/kit/asset-workflow/asset-pack-manifest.ts +320 -0
- package/src/kit/asset-workflow/asset-types.ts +142 -0
- package/src/kit/asset-workflow/audio-preview-player.ts +193 -0
- package/src/kit/asset-workflow/audio-waveform.ts +22 -0
- package/src/kit/asset-workflow/cloud-asset-client.ts +263 -0
- package/src/kit/asset-workflow/hosted-asset-materialization.ts +236 -0
- package/src/kit/asset-workflow/image-view-scale.ts +31 -0
- package/src/kit/asset-workflow/import-contract.ts +124 -0
- package/src/kit/asset-workflow/ledger-write-lock.ts +244 -0
- package/src/kit/asset-workflow/pixi-spritesheet.ts +197 -0
- package/src/kit/asset-workflow/preview-resource-lifetime.ts +44 -0
- package/src/kit/asset-workflow/project-asset-commands.ts +20 -0
- package/src/kit/asset-workflow/project-content.ts +288 -0
- package/src/kit/asset-workflow/project-source-index.ts +545 -0
- package/src/kit/asset-workflow/thumbnail-system.ts +256 -0
- package/src/kit/authoring/active-adapter.ts +200 -0
- package/src/kit/authoring/active-systems.ts +422 -0
- package/src/kit/authoring/adapter-key.ts +18 -0
- package/src/kit/authoring/authoring-asset-url.ts +27 -0
- package/src/kit/authoring/bootstrap-state.ts +49 -0
- package/src/kit/authoring/boundary-authoring-adapter.ts +189 -0
- package/src/kit/authoring/canvas-scene-guides.ts +84 -0
- package/src/kit/authoring/composite-authoring-adapter.ts +2109 -0
- package/src/kit/authoring/consumer-actions.ts +531 -0
- package/src/kit/authoring/design-time-layers.ts +852 -0
- package/src/kit/authoring/design-time-mount-registry.ts +244 -0
- package/src/kit/authoring/edit-mode-authoring.ts +637 -0
- package/src/kit/authoring/empty-project-authoring.ts +22 -0
- package/src/kit/authoring/instance-source-menu.ts +135 -0
- package/src/kit/authoring/layered-pick.ts +185 -0
- package/src/kit/authoring/mounted-root-subjects.ts +146 -0
- package/src/kit/authoring/no-authoring-adapter.ts +59 -0
- package/src/kit/authoring/object3d-document-persistence.ts +122 -0
- package/src/kit/authoring/panel-authoring.ts +121 -0
- package/src/kit/authoring/project-authoring-session.ts +105 -0
- package/src/kit/authoring/provenance.ts +99 -0
- package/src/kit/authoring/react-canvas-navigation.ts +259 -0
- package/src/kit/authoring/react-design-canvas-style.ts +20 -0
- package/src/kit/authoring/react-story-board.ts +917 -0
- package/src/kit/authoring/selection-scope.ts +195 -0
- package/src/kit/authoring/shell-document-ops.ts +169 -0
- package/src/kit/authoring/story-board-chrome-fit.ts +107 -0
- package/src/kit/authoring/story-board-presentation.ts +111 -0
- package/src/kit/authoring/three-root.ts +67 -0
- package/src/kit/authoring/viewport-tool-context.ts +73 -0
- package/src/kit/authoring/viewport-tool-owner.ts +38 -0
- package/src/kit/authoring/world-session-state.ts +101 -0
- package/src/kit/authoring-seam-evidence.ts +300 -0
- package/src/kit/availability-tick.ts +66 -0
- package/src/kit/bitmap-label.ts +120 -0
- package/src/kit/boot-routing.ts +392 -0
- package/src/kit/breakpoint-state.ts +43 -0
- package/src/kit/build-identity.ts +16 -0
- package/src/kit/bytes-codec.ts +62 -0
- package/src/kit/cancellation-reason.ts +58 -0
- package/src/kit/canvas-frames.ts +88 -0
- package/src/kit/capture-camera-pose.ts +77 -0
- package/src/kit/capture-size.ts +88 -0
- package/src/kit/chrome-registry.ts +159 -0
- package/src/kit/chrome-slot-registry.ts +91 -0
- package/src/kit/collaboration-client.ts +264 -0
- package/src/kit/collaboration-presence.ts +41 -0
- package/src/kit/command-dispatch.ts +19 -0
- package/src/kit/command-listener.ts +2182 -0
- package/src/kit/command-registry.ts +71 -0
- package/src/kit/component-board-registry.ts +205 -0
- package/src/kit/component-states-registry.ts +199 -0
- package/src/kit/components/AlignToolbar.tsx +204 -0
- package/src/kit/components/ApplicationMenus.tsx +372 -0
- package/src/kit/components/AssetEditorShell.tsx +216 -0
- package/src/kit/components/AssetInspectorToolSection.tsx +124 -0
- package/src/kit/components/BoardRulers.tsx +354 -0
- package/src/kit/components/CanvasAddNodeDialogs.tsx +529 -0
- package/src/kit/components/CanvasSceneViewport.tsx +1195 -0
- package/src/kit/components/ChromeSlot.tsx +20 -0
- package/src/kit/components/CodeView.tsx +470 -0
- package/src/kit/components/CompactInspectorShell.tsx +39 -0
- package/src/kit/components/ConsolePanel.tsx +273 -0
- package/src/kit/components/GameplaySessionTimeline.tsx +295 -0
- package/src/kit/components/InspectionProjection.tsx +932 -0
- package/src/kit/components/Inspector.tsx +270 -0
- package/src/kit/components/InspectorCanvasPreview.tsx +35 -0
- package/src/kit/components/InspectorFieldsSection.tsx +290 -0
- package/src/kit/components/InspectorStoriesSection.tsx +92 -0
- package/src/kit/components/InspectorToolSection.tsx +96 -0
- package/src/kit/components/InspectorTransformSection.tsx +245 -0
- package/src/kit/components/LightExplorerPanel.tsx +433 -0
- package/src/kit/components/MediaProperties.tsx +145 -0
- package/src/kit/components/ProjectHeader.tsx +328 -0
- package/src/kit/components/ReactCanvasControls.tsx +358 -0
- package/src/kit/components/RootSelectionOverlay.tsx +3688 -0
- package/src/kit/components/RootTextEditor.tsx +79 -0
- package/src/kit/components/SaveStatus.tsx +70 -0
- package/src/kit/components/SurfaceCrashBoundary.tsx +105 -0
- package/src/kit/components/SurfaceStateOverlay.tsx +24 -0
- package/src/kit/components/ToolContributionSurfaces.tsx +49 -0
- package/src/kit/components/ToolHost.tsx +380 -0
- package/src/kit/components/Toolbar.tsx +811 -0
- package/src/kit/components/TransientHint.tsx +44 -0
- package/src/kit/components/VersionControlSection.tsx +470 -0
- package/src/kit/components/ViewportOverlaysMenu.tsx +177 -0
- package/src/kit/components/VolterLogo.tsx +18 -0
- package/src/kit/components/WorktreeSwitcher.tsx +712 -0
- package/src/kit/components/account-documents.tsx +1162 -0
- package/src/kit/components/asset-documents.tsx +794 -0
- package/src/kit/components/asset-editor-persistence.ts +216 -0
- package/src/kit/components/asset-selection-section.tsx +545 -0
- package/src/kit/components/asset-thumbnails.tsx +307 -0
- package/src/kit/components/asset-viewers/AudioViewer.tsx +201 -0
- package/src/kit/components/asset-viewers/GenericJsonViewer.tsx +102 -0
- package/src/kit/components/asset-viewers/ImageViewer.tsx +300 -0
- package/src/kit/components/asset-viewers/JsonAssetDocument.tsx +98 -0
- package/src/kit/components/asset-viewers/OnlineAssetDetail.tsx +426 -0
- package/src/kit/components/asset-viewers/SourceAssetViewer.tsx +356 -0
- package/src/kit/components/asset-viewers/SpritesheetSpriteView.tsx +102 -0
- package/src/kit/components/asset-viewers/VideoViewer.tsx +101 -0
- package/src/kit/components/asset-viewers/shader-source.ts +144 -0
- package/src/kit/components/board-guides.ts +150 -0
- package/src/kit/components/canvas-scene-hotkeys.ts +37 -0
- package/src/kit/components/canvas-temporary-pivot.ts +34 -0
- package/src/kit/components/core-utilities.tsx +94 -0
- package/src/kit/components/inspector-preview-section.tsx +223 -0
- package/src/kit/components/inspector-revert-label.ts +20 -0
- package/src/kit/components/inspector-selection.ts +42 -0
- package/src/kit/components/inspector-stories-gating.ts +171 -0
- package/src/kit/components/inspector-transform-subject.ts +11 -0
- package/src/kit/components/inspector-transform.ts +88 -0
- package/src/kit/components/kind-documents.tsx +544 -0
- package/src/kit/components/primitives/DraftColorInput.tsx +74 -0
- package/src/kit/components/project-tool-documents.tsx +402 -0
- package/src/kit/components/scene-documents.tsx +221 -0
- package/src/kit/components/status-contributions.tsx +407 -0
- package/src/kit/components/tool-documents.tsx +302 -0
- package/src/kit/components/tool-schema-form.tsx +262 -0
- package/src/kit/components/use-after-paint.ts +41 -0
- package/src/kit/components/use-project-image-assets.ts +86 -0
- package/src/kit/components/workspace-history.ts +32 -0
- package/src/kit/components/world-documents.tsx +570 -0
- package/src/kit/components/world-overlay-gestures.ts +1939 -0
- package/src/kit/composite-screenshot.ts +2238 -0
- package/src/kit/content-entry-source-registry.ts +184 -0
- package/src/kit/contribution-surfaces.ts +48 -0
- package/src/kit/coverage/canvas-reveal.ts +192 -0
- package/src/kit/coverage/design-time-surfaces.ts +101 -0
- package/src/kit/coverage/ontology-invariants.ts +466 -0
- package/src/kit/coverage/session-vitals.ts +503 -0
- package/src/kit/crash-null-boundary.ts +36 -0
- package/src/kit/creation-site-edit.ts +1491 -0
- package/src/kit/creation-site-registry.ts +160 -0
- package/src/kit/delegate-harness-registry.ts +134 -0
- package/src/kit/document-areas.ts +70 -0
- package/src/kit/document-context-registry.ts +193 -0
- package/src/kit/document-open-registry.ts +200 -0
- package/src/kit/document-play-extension.ts +221 -0
- package/src/kit/document-preview-source.ts +20 -0
- package/src/kit/document-renderer-session.ts +138 -0
- package/src/kit/document-stage-sessions.ts +26 -0
- package/src/kit/document-viewports.ts +120 -0
- package/src/kit/editor-api.ts +46 -0
- package/src/kit/editor-chrome-capture.ts +136 -0
- package/src/kit/editor-commands.ts +176 -0
- package/src/kit/editor-console.ts +580 -0
- package/src/kit/editor-current-view.ts +56 -0
- package/src/kit/editor-document-probe.ts +1168 -0
- package/src/kit/editor-git-client.ts +115 -0
- package/src/kit/editor-hotkeys.ts +728 -0
- package/src/kit/editor-lease-view.ts +39 -0
- package/src/kit/editor-lease.ts +415 -0
- package/src/kit/editor-mode.ts +19 -0
- package/src/kit/editor-notifications.ts +140 -0
- package/src/kit/editor-presence.ts +563 -0
- package/src/kit/editor-presentation-activity.ts +58 -0
- package/src/kit/editor-presentation-notice.ts +42 -0
- package/src/kit/editor-runtime.tsx +147 -0
- package/src/kit/editor-server-response.ts +86 -0
- package/src/kit/editor-session-attribution.ts +85 -0
- package/src/kit/editor-session-mode.ts +54 -0
- package/src/kit/editor-state-facets.ts +74 -0
- package/src/kit/editor-view-presentation.ts +777 -0
- package/src/kit/environment-images.ts +58 -0
- package/src/kit/eyedropper-session.ts +60 -0
- package/src/kit/files/file-provider.ts +62 -0
- package/src/kit/files/project-files.ts +270 -0
- package/src/kit/finders/index.ts +137 -0
- package/src/kit/finders/scenes-from-entrypoint-selection.ts +387 -0
- package/src/kit/frame/frame-parts.ts +30 -0
- package/src/kit/framed-document-capture.ts +34 -0
- package/src/kit/game-globals-prelude.ts +143 -0
- package/src/kit/game-surface-defaults.ts +33 -0
- package/src/kit/gameplay-dom-recording.ts +318 -0
- package/src/kit/gameplay-export-state.ts +14 -0
- package/src/kit/gameplay-replay.ts +417 -0
- package/src/kit/gameplay-session-time.ts +9 -0
- package/src/kit/gameplay-sessions.ts +204 -0
- package/src/kit/hierarchy-component-marks.ts +298 -0
- package/src/kit/hierarchy-internals.ts +197 -0
- package/src/kit/hierarchy-kind-icon.ts +217 -0
- package/src/kit/hierarchy-menu-registry.ts +67 -0
- package/src/kit/hierarchy-node-rows.ts +307 -0
- package/src/kit/hierarchy-panel-view.ts +280 -0
- package/src/kit/hierarchy-projection.ts +76 -0
- package/src/kit/hierarchy-row-media.ts +45 -0
- package/src/kit/hierarchy-row-model.ts +308 -0
- package/src/kit/hierarchy-rows.ts +11 -0
- package/src/kit/hierarchy-walk.ts +86 -0
- package/src/kit/history/editor-session.ts +25 -0
- package/src/kit/history/history-commands.ts +147 -0
- package/src/kit/history/history-delegate.ts +187 -0
- package/src/kit/history/history-limit-notices.ts +43 -0
- package/src/kit/history/history-service.ts +1189 -0
- package/src/kit/history/persistence-coordinator.ts +35 -0
- package/src/kit/history/project-file-history.ts +386 -0
- package/src/kit/history/project-root-history-backends.ts +139 -0
- package/src/kit/history/resource-registry.ts +209 -0
- package/src/kit/history/snapshot-store.ts +103 -0
- package/src/kit/history/source-history-backend.ts +546 -0
- package/src/kit/history-types.ts +124 -0
- package/src/kit/hmr-registration-group.ts +67 -0
- package/src/kit/hmr-stable-react-context.ts +23 -0
- package/src/kit/hotkeys.ts +190 -0
- package/src/kit/inference-diagnostics.ts +69 -0
- package/src/kit/initial-project.ts +80 -0
- package/src/kit/inspection/active-subject.ts +571 -0
- package/src/kit/inspection/active-surface.ts +142 -0
- package/src/kit/inspection/compose-subject.ts +1055 -0
- package/src/kit/inspection/compose.ts +7 -0
- package/src/kit/inspection/display.ts +171 -0
- package/src/kit/inspection/document-subject.ts +109 -0
- package/src/kit/inspection/game-subject.ts +85 -0
- package/src/kit/inspection/null-subject.ts +119 -0
- package/src/kit/inspection/serialize.ts +357 -0
- package/src/kit/inspection/use-active-inspection.ts +180 -0
- package/src/kit/inspection-model.ts +542 -0
- package/src/kit/inspection-node-media.ts +58 -0
- package/src/kit/inspector-presentation.ts +203 -0
- package/src/kit/inspector-property-grouping.ts +64 -0
- package/src/kit/inspector-section-registry.ts +221 -0
- package/src/kit/instance-source-actions.ts +163 -0
- package/src/kit/js-heap.ts +71 -0
- package/src/kit/key-actions.ts +91 -0
- package/src/kit/keymap-presets.ts +428 -0
- package/src/kit/layout-policy.ts +31 -0
- package/src/kit/light-explorer-model.ts +134 -0
- package/src/kit/live-canvas-frame.ts +55 -0
- package/src/kit/live-document.ts +296 -0
- package/src/kit/live-gesture-lock.ts +50 -0
- package/src/kit/live-seam-evidence.ts +11 -0
- package/src/kit/live-session-registry.ts +220 -0
- package/src/kit/live-transition.ts +391 -0
- package/src/kit/manifest-project.ts +107 -0
- package/src/kit/module-fetch-diagnosis.ts +192 -0
- package/src/kit/mount-failure-report.ts +154 -0
- package/src/kit/native-selection-style.ts +497 -0
- package/src/kit/object3d-document-write-policy.ts +137 -0
- package/src/kit/packaged-runtime.ts +108 -0
- package/src/kit/palettes/maya.palette.json +57 -0
- package/src/kit/palettes/substance.palette.json +57 -0
- package/src/kit/performance-profiler.ts +367 -0
- package/src/kit/performance-sources.ts +69 -0
- package/src/kit/photograph-notice.ts +141 -0
- package/src/kit/play-boot-phase.ts +166 -0
- package/src/kit/play-camera-flight.ts +35 -0
- package/src/kit/png-encode.worker.ts +26 -0
- package/src/kit/presentation-surface.ts +248 -0
- package/src/kit/product-command.ts +90 -0
- package/src/kit/project-adapter.ts +1140 -0
- package/src/kit/project-asset-refresh.ts +23 -0
- package/src/kit/project-asset-roots.ts +68 -0
- package/src/kit/project-local-state.ts +151 -0
- package/src/kit/project-manager.ts +243 -0
- package/src/kit/project-module-changes.ts +201 -0
- package/src/kit/project-module-split.ts +270 -0
- package/src/kit/project-play-layers.ts +25 -0
- package/src/kit/project-provenance.ts +115 -0
- package/src/kit/project-ready.ts +42 -0
- package/src/kit/project-shape.ts +68 -0
- package/src/kit/project-tools.ts +107 -0
- package/src/kit/projection-types.ts +44 -0
- package/src/kit/readiness.ts +113 -0
- package/src/kit/renderer-resource-counts.ts +27 -0
- package/src/kit/reported-play-state.ts +90 -0
- package/src/kit/resolve-contributed-command.ts +14 -0
- package/src/kit/resolve-relative-specifier.ts +33 -0
- package/src/kit/retained-document-states.ts +91 -0
- package/src/kit/scene-document-plan.ts +320 -0
- package/src/kit/scene-live-open.ts +210 -0
- package/src/kit/scoped-game-css.ts +152 -0
- package/src/kit/served-url.ts +5 -0
- package/src/kit/session-close.ts +17 -0
- package/src/kit/session-tombstone.ts +127 -0
- package/src/kit/settings/settings-provider.ts +82 -0
- package/src/kit/settings-store.ts +348 -0
- package/src/kit/shell-document-state.ts +27 -0
- package/src/kit/shell-store-door.ts +45 -0
- package/src/kit/shell-store.ts +722 -0
- package/src/kit/source-conflict.ts +122 -0
- package/src/kit/stage-context.ts +377 -0
- package/src/kit/stage-invalidation.ts +25 -0
- package/src/kit/stage-store-registry.ts +69 -0
- package/src/kit/startup-failure.ts +80 -0
- package/src/kit/state-report-deferral.ts +73 -0
- package/src/kit/storage/host-files-storage.ts +97 -0
- package/src/kit/storage/http-storage.ts +174 -0
- package/src/kit/storage/index.ts +75 -0
- package/src/kit/storage/mem-storage.ts +158 -0
- package/src/kit/storage/path-lock.ts +44 -0
- package/src/kit/storage/paths.ts +26 -0
- package/src/kit/storage-types.ts +127 -0
- package/src/kit/stories/StoryPreviewMount.tsx +306 -0
- package/src/kit/stories/compose-project-stories.ts +255 -0
- package/src/kit/stories/prefabs-finder.ts +54 -0
- package/src/kit/stories/prefabs-from-stories.ts +182 -0
- package/src/kit/stories/project-story-regions.ts +24 -0
- package/src/kit/stories/story-capture.ts +579 -0
- package/src/kit/stories/story-declared-medium.ts +126 -0
- package/src/kit/stories/story-discovery.ts +176 -0
- package/src/kit/stories/story-dom-runtime.ts +78 -0
- package/src/kit/stories/story-grouping.ts +111 -0
- package/src/kit/stories/story-mount-turn.ts +27 -0
- package/src/kit/stories/story-presentation.ts +215 -0
- package/src/kit/stories/story-preview-component.ts +7 -0
- package/src/kit/stories/story-registry.ts +530 -0
- package/src/kit/stories-scope.ts +35 -0
- package/src/kit/story-document-openers.ts +36 -0
- package/src/kit/story-thumbnails.ts +47 -0
- package/src/kit/surface-keyboard.ts +101 -0
- package/src/kit/surface-state.ts +135 -0
- package/src/kit/system-seam-evidence.ts +72 -0
- package/src/kit/tab-census.ts +202 -0
- package/src/kit/tab-lifecycle-client.ts +227 -0
- package/src/kit/theme-library.ts +897 -0
- package/src/kit/theme-preference.ts +429 -0
- package/src/kit/three-viewport-presentation.ts +23 -0
- package/src/kit/tool-contribution-play.ts +74 -0
- package/src/kit/tool-loader.ts +1918 -0
- package/src/kit/transform-mode-request.ts +66 -0
- package/src/kit/transient-hint.ts +78 -0
- package/src/kit/transport-strip.tsx +174 -0
- package/src/kit/ui-source/adapter-region-includes.ts +238 -0
- package/src/kit/ui-source/file-region-resolver.ts +302 -0
- package/src/kit/ui-source/inspect.ts +775 -0
- package/src/kit/ui-source/source-write-backend.ts +605 -0
- package/src/kit/ui-source/tier-source-write-backend.ts +279 -0
- package/src/kit/user-local-state.ts +105 -0
- package/src/kit/viewport-activation-timings.ts +840 -0
- package/src/kit/viewport-editor-controls.ts +22 -0
- package/src/kit/viewport-presentation.ts +668 -0
- package/src/kit/viewport-surface-status.tsx +55 -0
- package/src/kit/wait-until.ts +37 -0
- package/src/kit/worker-call-metrics.ts +166 -0
- package/src/kit/workspace-areas.ts +191 -0
- package/src/kit/workspace-aux-commands.ts +11 -0
- package/src/kit/workspace-available-documents.ts +142 -0
- package/src/kit/workspace-core-utilities.ts +31 -0
- package/src/kit/workspace-document-ids.ts +59 -0
- package/src/kit/workspace-document-registry.ts +624 -0
- package/src/kit/workspace-document-restore.ts +146 -0
- package/src/kit/workspace-host-commands.ts +141 -0
- package/src/kit/workspace-persistence-gate.ts +40 -0
- package/src/kit/workspace-play-utilities.ts +44 -0
- package/src/kit/workspace-presets.ts +446 -0
- package/src/kit/workspace-regions.ts +276 -0
- package/src/kit/workspace-static-panels.ts +73 -0
- package/src/kit/workspace-status-registry.ts +121 -0
- package/src/kit/workspace-storage.ts +35 -0
- package/src/kit/workspace-style.ts +226 -0
- package/src/kit/workspace-utility-commands.ts +74 -0
- package/src/kit/workspace-utility-registry.ts +263 -0
- package/src/kit/world-adoption-event.ts +23 -0
- package/src/kit/world-adoption.ts +115 -0
- package/src/kit/world-canvas-viewport-state.ts +35 -0
- package/src/kit/world-document-routing.ts +104 -0
- package/src/kit/world-pan-state.ts +198 -0
- package/src/kit/write-pipe.ts +173 -0
- package/src/layout-arrangements.ts +5 -0
- package/src/layouts.tsx +108 -0
- package/src/looks.ts +16 -0
- package/src/project/output-roots.ts +73 -0
- package/src/project/tab-census.ts +155 -0
- package/src/project-tool-catalog.ts +104 -0
- package/src/selection.tsx +107 -0
- package/src/services.ts +18 -0
- package/src/session/build-report.ts +22 -0
- package/src/session/collaboration-types.ts +262 -0
- package/src/session/command-table.ts +327 -0
- package/src/session/discovery.ts +100 -0
- package/src/session/editor-brand.ts +48 -0
- package/src/session/editor-compatibility.ts +329 -0
- package/src/session/editor-control-lifecycle.ts +68 -0
- package/src/session/editor-control-protocol.ts +5 -0
- package/src/session/entrypoint-selection-readers.ts +66 -0
- package/src/session/entrypoint-selection-source.ts +120 -0
- package/src/session/game-css-scope.ts +30 -0
- package/src/session/hosted-attachment.ts +225 -0
- package/src/session/limited-view.ts +82 -0
- package/src/session/product-create.ts +24 -0
- package/src/session/product-locator.ts +478 -0
- package/src/session/project-module-url.ts +242 -0
- package/src/session/project-serving.ts +164 -0
- package/src/session/project-upgrade.ts +669 -0
- package/src/session/registry-format.ts +210 -0
- package/src/session/relative-path-guard.ts +56 -0
- package/src/session/scoped-game-css.ts +461 -0
- package/src/session/source-glob.ts +15 -0
- package/src/session/tool-contribution-convention.ts +123 -0
- package/src/session/workbench-locator.ts +712 -0
- package/src/session.ts +41 -0
- package/src/share.ts +160 -0
- package/src/source-analysis.ts +28 -0
- package/src/source-authoring.ts +439 -0
- package/src/tools/errors.ts +91 -0
- package/src/tools/provider-execution.ts +70 -0
- package/src/tools/registry.ts +341 -0
- package/src/tools/types.ts +159 -0
- package/src/transport.ts +100 -0
- package/src/types.ts +1693 -0
- package/src/views.ts +164 -0
- package/src/widgets/design-system.ts +93 -0
- package/src/widgets/editor-appearance.ts +151 -0
- package/src/widgets/editor-material.ts +83 -0
- package/src/widgets/icon-set-registry.ts +105 -0
- package/src/widgets/index.ts +71 -0
- package/src/widgets/inspector-widgets/AlignmentGrid.tsx +182 -0
- package/src/widgets/inspector-widgets/AssetSlotPicker.tsx +123 -0
- package/src/widgets/inspector-widgets/BorderEditor.tsx +309 -0
- package/src/widgets/inspector-widgets/ColorPicker.tsx +549 -0
- package/src/widgets/inspector-widgets/CurveEditor.tsx +359 -0
- package/src/widgets/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/widgets/inspector-widgets/FontPicker.tsx +191 -0
- package/src/widgets/inspector-widgets/GradientEditor.tsx +623 -0
- package/src/widgets/inspector-widgets/ScrubbableInput.tsx +180 -0
- package/src/widgets/inspector-widgets/ShadowEditor.tsx +319 -0
- package/src/widgets/inspector-widgets/color-utils.ts +201 -0
- package/src/widgets/inspector-widgets/curve-utils.ts +212 -0
- package/src/widgets/inspector-widgets/index.ts +25 -0
- package/src/widgets/inspector-widgets/shared.tsx +140 -0
- package/src/widgets/interactive-edit-scope.ts +33 -0
- package/src/widgets/patterns/Dialog.tsx +140 -0
- package/src/widgets/patterns/Fields.tsx +44 -0
- package/src/widgets/patterns/List.tsx +25 -0
- package/src/widgets/patterns/StateSurface.tsx +40 -0
- package/src/widgets/patterns/Surfaces.tsx +122 -0
- package/src/widgets/patterns/Tabs.tsx +80 -0
- package/src/widgets/patterns/Toolbar.tsx +72 -0
- package/src/widgets/patterns/Tree.tsx +72 -0
- package/src/widgets/primitives/AnchoredMenu.tsx +260 -0
- package/src/widgets/primitives/Button.tsx +62 -0
- package/src/widgets/primitives/ColorInput.tsx +78 -0
- package/src/widgets/primitives/DraftTextInput.tsx +63 -0
- package/src/widgets/primitives/EditorIcon.tsx +157 -0
- package/src/widgets/primitives/FormControls.tsx +88 -0
- package/src/widgets/primitives/HoverPreview.tsx +96 -0
- package/src/widgets/primitives/JsonInput.tsx +113 -0
- package/src/widgets/primitives/Layout.tsx +100 -0
- package/src/widgets/primitives/Menu.tsx +161 -0
- package/src/widgets/primitives/NumberInput.tsx +169 -0
- package/src/widgets/primitives/Panel.tsx +80 -0
- package/src/widgets/primitives/SectionHeader.tsx +77 -0
- package/src/widgets/primitives/Text.tsx +54 -0
- package/src/widgets/primitives/ThemeRootPortal.tsx +52 -0
- package/src/widgets/primitives/Tooltip.tsx +204 -0
- package/src/widgets/primitives/Vec3Input.tsx +70 -0
- package/src/widgets/primitives/banner-tones.ts +32 -0
- package/src/widgets/primitives/clamp-to-viewport.ts +44 -0
- package/src/widgets/primitives/editor-icons.ts +254 -0
- package/src/widgets/primitives/panel-header-styles.ts +42 -0
- package/src/widgets/theme.ts +2841 -0
- package/src/widgets/z-index.ts +25 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ENVIRONMENT IMAGES: panoramas a view can light by and draw behind the scene
|
|
3
|
+
* (`PreviewLighting.environment.image`), registered as data by the integration
|
|
4
|
+
* that ships them (a `*.environment.ts` contribution, point `workspace.environment`).
|
|
5
|
+
* A view names an image by id, never by URL: the URL is a built asset's, which a
|
|
6
|
+
* rebuild renames, and a saved view outlives the build that wrote it.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export interface EnvironmentImage {
|
|
10
|
+
readonly id: string;
|
|
11
|
+
readonly title: string;
|
|
12
|
+
/** The image as served: an equirectangular panorama in scene-referred light. */
|
|
13
|
+
readonly url: string;
|
|
14
|
+
readonly format: 'exr' | 'hdr';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** What a `*.environment.ts` contribution exports as `environment`: one integration's images. */
|
|
18
|
+
export interface EnvironmentImageSet {
|
|
19
|
+
readonly id: string;
|
|
20
|
+
/** Where the images come from and under what terms, as the shipping integration states it. */
|
|
21
|
+
readonly source: string;
|
|
22
|
+
readonly images: readonly EnvironmentImage[];
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const images = new Map<string, EnvironmentImage>();
|
|
26
|
+
const listeners = new Set<() => void>();
|
|
27
|
+
|
|
28
|
+
function changed(): void {
|
|
29
|
+
for (const listener of listeners) listener();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Register a set's images; returns the unregister. An id already registered is refused. */
|
|
33
|
+
export function registerEnvironmentImages(set: EnvironmentImageSet): () => void {
|
|
34
|
+
for (const image of set.images) {
|
|
35
|
+
if (images.has(image.id)) throw new Error(`registerEnvironmentImages: "${image.id}" is already registered.`);
|
|
36
|
+
}
|
|
37
|
+
for (const image of set.images) images.set(image.id, image);
|
|
38
|
+
changed();
|
|
39
|
+
return () => {
|
|
40
|
+
for (const image of set.images) if (images.get(image.id) === image) images.delete(image.id);
|
|
41
|
+
changed();
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function environmentImage(id: string): EnvironmentImage | null {
|
|
46
|
+
return images.get(id) ?? null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function environmentImages(): readonly EnvironmentImage[] {
|
|
50
|
+
return [...images.values()];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function subscribeEnvironmentImages(listener: () => void): () => void {
|
|
54
|
+
listeners.add(listener);
|
|
55
|
+
return () => {
|
|
56
|
+
listeners.delete(listener);
|
|
57
|
+
};
|
|
58
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Eyedropper session (D3.d) — a module-level subscribable singleton bridging the
|
|
3
|
+
* C1 `ColorPicker` (mounted inside the Inspector panel) and the canvas
|
|
4
|
+
* (`RootSelectionOverlay`), the two SIBLING React trees a "click the eyedropper
|
|
5
|
+
* button, then click somewhere on the canvas" gesture must cross when the native
|
|
6
|
+
* `EyeDropper` API is unavailable (the FALLBACK path this whole module exists
|
|
7
|
+
* for — see `ColorPicker.tsx`'s `handleEyedropper` and the `ColorSampleProvider`
|
|
8
|
+
* contract doc comment for why the native path needs none of this: it samples
|
|
9
|
+
* real rendered pixels itself).
|
|
10
|
+
*
|
|
11
|
+
* Mirrors `world-session-state.ts`'s "bare module singleton" shape, but keeps
|
|
12
|
+
* its OWN subscriber list (rather than piggybacking on `EditorShellStore.
|
|
13
|
+
* notifyIngestEdit`) since this is transient cross-panel UI state, not an
|
|
14
|
+
* authored/session toggle any editor-store snapshot needs to carry.
|
|
15
|
+
*
|
|
16
|
+
* Only ONE fallback pick can be in flight at a time — beginning a new one
|
|
17
|
+
* silently supersedes whatever was pending (mirrors the ColorPicker's own
|
|
18
|
+
* "one popover at a time" assumption; nothing today opens two eyedroppers at
|
|
19
|
+
* once).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export type EyedropperApply = (color: string | null) => void;
|
|
23
|
+
|
|
24
|
+
let activeApply: EyedropperApply | null = null;
|
|
25
|
+
const listeners = new Set<() => void>();
|
|
26
|
+
|
|
27
|
+
function notify(): void {
|
|
28
|
+
for (const l of listeners) l();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Begin a fallback eyedropper session — `apply` is the widget's own
|
|
32
|
+
* sampled-color callback, called exactly once when the session resolves
|
|
33
|
+
* (`null` color means "cancelled", e.g. Escape — never a fabricated color). */
|
|
34
|
+
export function beginEyedropperSession(apply: EyedropperApply): void {
|
|
35
|
+
activeApply = apply;
|
|
36
|
+
notify();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** True while a fallback session is awaiting a canvas click/Escape. */
|
|
40
|
+
export function isEyedropperSessionActive(): boolean {
|
|
41
|
+
return activeApply !== null;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Resolve the active session with a sampled color (or `null` to cancel),
|
|
45
|
+
* then close it. A no-op if no session is active. */
|
|
46
|
+
export function resolveEyedropperSession(color: string | null): void {
|
|
47
|
+
const apply = activeApply;
|
|
48
|
+
if (!apply) return;
|
|
49
|
+
activeApply = null;
|
|
50
|
+
notify();
|
|
51
|
+
apply(color);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Subscribe to session begin/end transitions — `RootSelectionOverlay` binds
|
|
55
|
+
* this via `useSyncExternalStore` so it re-renders (shows/hides the cursor
|
|
56
|
+
* swatch) the instant a session starts or ends. */
|
|
57
|
+
export function subscribeEyedropperSession(listener: () => void): () => void {
|
|
58
|
+
listeners.add(listener);
|
|
59
|
+
return () => listeners.delete(listener);
|
|
60
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE PROJECT'S FILES, WRITTEN THROUGH THE WORKBENCH — the provider it
|
|
3
|
+
* installs here, and the window before it lands.
|
|
4
|
+
*
|
|
5
|
+
* `EditorHost.files` is the door (`packages/sdk/src/kit/files/`) —
|
|
6
|
+
* read/readBytes/write/exists/list/watch over PROJECT-RELATIVE paths, the same
|
|
7
|
+
* spelling the history door hands over, so both resolve against one workspace
|
|
8
|
+
* folder.
|
|
9
|
+
*
|
|
10
|
+
* WHAT THE PROVIDER BUYS, measured (U5): a volter write the workbench did not
|
|
11
|
+
* make is an EXTERNAL change to it — Monaco reloads the file,
|
|
12
|
+
* `modelService.updateModel` pushes a fresh text element through `EditStack`,
|
|
13
|
+
* and `IUndoRedoService.pushElement` clears that resource's FUTURE, so a gizmo
|
|
14
|
+
* drag's redo was lost whenever a text model for that file was open. A write
|
|
15
|
+
* made THROUGH the workbench is the workbench's own, so no reload fires and
|
|
16
|
+
* the future survives. That is what this buys, and nothing else.
|
|
17
|
+
*
|
|
18
|
+
* IT ARRIVES AFTER THE MOUNT, always: a `ServicesAccessor` is valid only for
|
|
19
|
+
* the synchronous part of a command, so the contribution cannot build the
|
|
20
|
+
* provider before the mount it is handed to. Until it does, the door falls
|
|
21
|
+
* back to the session's transports — a write in that window is a real write
|
|
22
|
+
* with nowhere else to go.
|
|
23
|
+
*/
|
|
24
|
+
import type { EditorHostFileEvent, EditorHostFileProvider } from '@volter/sdk/host';
|
|
25
|
+
|
|
26
|
+
export type ProjectFileEvent = EditorHostFileEvent;
|
|
27
|
+
export type ProjectFileProvider = EditorHostFileProvider;
|
|
28
|
+
|
|
29
|
+
let provider: ProjectFileProvider | null = null;
|
|
30
|
+
const listeners = new Set<() => void>();
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Is the provider installed? False until it lands — later than the mount,
|
|
34
|
+
* because a `ServicesAccessor` is valid only for a command's synchronous part,
|
|
35
|
+
* so the contribution hands the provider over after the editor is running. In
|
|
36
|
+
* that window a caller reaches the session's transports instead, which is a
|
|
37
|
+
* real write with nowhere else to go rather than a refusal.
|
|
38
|
+
*/
|
|
39
|
+
export function filesProviderInstalled(): boolean {
|
|
40
|
+
return provider !== null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The installed provider, or `null` before it lands. */
|
|
44
|
+
export function filesProvider(): ProjectFileProvider | null {
|
|
45
|
+
return provider;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Install how the project's files are read and written, or `null` to withdraw
|
|
50
|
+
* it — the provider is the workbench's, and a workbench that went away takes
|
|
51
|
+
* it with it.
|
|
52
|
+
*/
|
|
53
|
+
export function setFilesProvider(next: ProjectFileProvider | null): void {
|
|
54
|
+
if (provider === next) return;
|
|
55
|
+
provider = next;
|
|
56
|
+
for (const listener of listeners) listener();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function subscribeFilesProvider(listener: () => void): () => void {
|
|
60
|
+
listeners.add(listener);
|
|
61
|
+
return () => listeners.delete(listener);
|
|
62
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE ONE FILE API over the open project, in PROJECT-RELATIVE paths — the
|
|
3
|
+
* editor's half of `@volter/sdk/host`'s `files` door (U5).
|
|
4
|
+
*
|
|
5
|
+
* Under the FRAME this is VS Code's `IFileService`/`ITextFileService` over the
|
|
6
|
+
* workspace folder, installed as a provider by the Code-OSS bridge. Under the
|
|
7
|
+
* HOST — standalone the editor's `edit` command, and the hosted browser build — it is today's
|
|
8
|
+
* transports, and this module is the ONE place that says which transport owns
|
|
9
|
+
* which path. That statement used to be spread across five files' doc
|
|
10
|
+
* comments; it is written down once, here, because the fragmentation is the
|
|
11
|
+
* fact U5 measured:
|
|
12
|
+
*
|
|
13
|
+
* | path class | the session's route |
|
|
14
|
+
* |-----------------------|------------------------------|
|
|
15
|
+
* | read, anything | Vite `/@fs/<root>/<path>` |
|
|
16
|
+
* | write `public/**` | `POST /__editor/save-file` |
|
|
17
|
+
* | write `.volter/**` | `POST /__editor/volter-file` |
|
|
18
|
+
* | write `src/**` source | `POST /__ui-source/apply` | the storage source-write backend |
|
|
19
|
+
* | list `public/**` | `GET /__editor/assets` | StorageBackend |
|
|
20
|
+
* | watch | `EventSource /__editor/events` | StorageBackend.watch |
|
|
21
|
+
*
|
|
22
|
+
* A path class with no host transport is REFUSED BY NAME, naming the route
|
|
23
|
+
* that does own it. It is not this door's business to invent a general
|
|
24
|
+
* project-root write route on the session: each of those routes is
|
|
25
|
+
* deliberately narrow (`/__editor/volter-file` accepts only `.volter/**`,
|
|
26
|
+
* `/__editor/data-file` only `src/data/**\/*.data.json`), and their own header
|
|
27
|
+
* comments record that as defence in depth. Under the frame the question does
|
|
28
|
+
* not arise — the workbench's file service owns the whole folder.
|
|
29
|
+
*
|
|
30
|
+
* `StorageBackend`'s paths are NOT this door's paths, and that difference is
|
|
31
|
+
* the measurement the door exists for: `HttpStorage` is rooted at
|
|
32
|
+
* `<project>/public/` while a project-rooted backend is rooted at the
|
|
33
|
+
* project root. Callers that still speak `StorageBackend` keep doing so; what
|
|
34
|
+
* they get under the frame is `storage/host-files-storage.ts`, a `public/`
|
|
35
|
+
* view onto this door.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import { bytesToBase64 } from '@volter/sdk/kit/bytes-codec';
|
|
39
|
+
import { getProjectDefinePath } from '../editor-mode';
|
|
40
|
+
import { assertEditorServerAnswered, editorServerJson } from '@volter/sdk/kit/editor-server-response';
|
|
41
|
+
import { sourceMutationAttribution } from '@volter/sdk/kit/editor-session-attribution';
|
|
42
|
+
import { filesProvider, filesProviderInstalled, type ProjectFileEvent } from './file-provider';
|
|
43
|
+
|
|
44
|
+
const BASE = '/__editor';
|
|
45
|
+
|
|
46
|
+
export interface ProjectFileEntry {
|
|
47
|
+
readonly name: string;
|
|
48
|
+
readonly path: string;
|
|
49
|
+
readonly type: 'file' | 'dir';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Project-relative, `/`-separated, no leading slash, no `..`. */
|
|
53
|
+
function normalize(path: string): string {
|
|
54
|
+
return path.replace(/\\/g, '/').replace(/^\/+/, '').replace(/\/+$/, '');
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function assertContained(path: string): string {
|
|
58
|
+
const normalized = normalize(path);
|
|
59
|
+
if (!normalized || normalized.split('/').includes('..')) {
|
|
60
|
+
throw new Error(`projectFiles: "${path}" is not a project-relative path.`);
|
|
61
|
+
}
|
|
62
|
+
return normalized;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The same containment check for a DIRECTORY, where the empty string is the
|
|
67
|
+
* project root and therefore legal.
|
|
68
|
+
*
|
|
69
|
+
* It exists because `list` ran bare {@link normalize} while every other member
|
|
70
|
+
* ran {@link assertContained} — so a `..` segment reached the frame's provider
|
|
71
|
+
* or a session route while the same segment in a `read` was refused here.
|
|
72
|
+
* `normalize` strips a LEADING slash; it has never removed a `..` segment, and
|
|
73
|
+
* a caller reading its name could be forgiven for thinking otherwise. The
|
|
74
|
+
* empty string is the one thing `assertContained` rejects that a directory
|
|
75
|
+
* legitimately needs (it is how the project root itself is listed), which is
|
|
76
|
+
* why this is a second function rather than a flag.
|
|
77
|
+
*/
|
|
78
|
+
function assertContainedDir(dir: string): string {
|
|
79
|
+
const normalized = normalize(dir);
|
|
80
|
+
if (normalized.split('/').includes('..')) {
|
|
81
|
+
throw new Error(`projectFiles: "${dir}" is not a project-relative directory.`);
|
|
82
|
+
}
|
|
83
|
+
return normalized;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The refusal a host-tier write to a path class no session route owns gets.
|
|
88
|
+
* It NAMES the owning route rather than failing generically, because the one
|
|
89
|
+
* thing a caller can do about it is use that route.
|
|
90
|
+
*/
|
|
91
|
+
function noHostWriteRoute(path: string): Error {
|
|
92
|
+
return new Error(
|
|
93
|
+
`projectFiles.write("${path}"): the standalone editor has no general project-root write route, ` +
|
|
94
|
+
'and this door does not invent one. Source files are written through `/__ui-source/apply` ' +
|
|
95
|
+
'(`ui-source/source-write-backend.ts`), `public/**` through `/__editor/save-file`, `.volter/**` ' +
|
|
96
|
+
'through `/__editor/volter-file`. Under the Code-OSS frame the workbench file service owns the ' +
|
|
97
|
+
'whole folder and this refusal cannot occur.',
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// The HOST fill — today's transports
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
async function hostRead(path: string): Promise<string> {
|
|
106
|
+
const res = await fetch(`/@fs/${getProjectDefinePath()}/${path}`);
|
|
107
|
+
if (!res.ok) throw new Error(`projectFiles.read "${path}": HTTP ${res.status}`);
|
|
108
|
+
return res.text();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async function hostReadBytes(path: string): Promise<Uint8Array> {
|
|
112
|
+
const res = await fetch(`/@fs/${getProjectDefinePath()}/${path}`);
|
|
113
|
+
if (!res.ok) throw new Error(`projectFiles.readBytes "${path}": HTTP ${res.status}`);
|
|
114
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function hostWrite(path: string, data: string | Uint8Array): Promise<void> {
|
|
118
|
+
if (path.startsWith('public/')) {
|
|
119
|
+
const body =
|
|
120
|
+
typeof data === 'string'
|
|
121
|
+
? { path: path.slice('public/'.length), content: data, ...sourceMutationAttribution() }
|
|
122
|
+
: {
|
|
123
|
+
path: path.slice('public/'.length),
|
|
124
|
+
content: bytesToBase64(data),
|
|
125
|
+
encoding: 'base64' as const,
|
|
126
|
+
...sourceMutationAttribution(),
|
|
127
|
+
};
|
|
128
|
+
const res = await fetch(`${BASE}/save-file`, {
|
|
129
|
+
method: 'POST',
|
|
130
|
+
headers: { 'Content-Type': 'application/json' },
|
|
131
|
+
body: JSON.stringify(body),
|
|
132
|
+
});
|
|
133
|
+
assertEditorServerAnswered(res, `Write ${path} failed`);
|
|
134
|
+
if (!res.ok) throw new Error(`projectFiles.write "${path}": HTTP ${res.status}`);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (path.startsWith('.volter/')) {
|
|
138
|
+
const body =
|
|
139
|
+
typeof data === 'string'
|
|
140
|
+
? { path, content: data, ...sourceMutationAttribution() }
|
|
141
|
+
: {
|
|
142
|
+
path,
|
|
143
|
+
content: bytesToBase64(data),
|
|
144
|
+
encoding: 'base64' as const,
|
|
145
|
+
...sourceMutationAttribution(),
|
|
146
|
+
};
|
|
147
|
+
const res = await fetch(`${BASE}/volter-file`, {
|
|
148
|
+
method: 'POST',
|
|
149
|
+
headers: { 'Content-Type': 'application/json' },
|
|
150
|
+
body: JSON.stringify(body),
|
|
151
|
+
});
|
|
152
|
+
assertEditorServerAnswered(res, `Write ${path} failed`);
|
|
153
|
+
if (!res.ok) throw new Error(`projectFiles.write "${path}": HTTP ${res.status}`);
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
throw noHostWriteRoute(path);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async function hostExists(path: string): Promise<boolean> {
|
|
160
|
+
try {
|
|
161
|
+
const res = await fetch(`/@fs/${getProjectDefinePath()}/${path}`, { method: 'HEAD' });
|
|
162
|
+
// The dev server's SPA fallback answers 200 with `index.html` for a missing
|
|
163
|
+
// path, so `res.ok` alone cannot tell existence from absence — the same
|
|
164
|
+
// measured false positive `api/project-source.ts`'s `probeProjectFile`
|
|
165
|
+
// records. A real file never answers as an HTML DOCUMENT.
|
|
166
|
+
if (!res.ok) return false;
|
|
167
|
+
return !(res.headers.get('content-type') ?? '').toLowerCase().includes('text/html');
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
interface ServerAssetEntry {
|
|
174
|
+
name: string;
|
|
175
|
+
type: 'file' | 'directory';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async function hostList(dir: string): Promise<readonly ProjectFileEntry[]> {
|
|
179
|
+
if (!dir.startsWith('public')) {
|
|
180
|
+
throw new Error(
|
|
181
|
+
`projectFiles.list("${dir}"): the standalone editor lists only \`public/**\` ` +
|
|
182
|
+
'(`/__editor/assets`); source trees are listed by glob through ' +
|
|
183
|
+
"`/__editor/source-files` (`api/project-source.ts`'s `listProjectSourceFiles`).",
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
const inner = dir === 'public' ? '' : dir.slice('public/'.length);
|
|
187
|
+
const res = await fetch(`${BASE}/assets?${new URLSearchParams({ dir: inner })}`);
|
|
188
|
+
const { entries } = await editorServerJson<{ entries: ServerAssetEntry[] }>(
|
|
189
|
+
res,
|
|
190
|
+
`projectFiles.list "${dir}" failed`,
|
|
191
|
+
);
|
|
192
|
+
return entries.map((entry) => ({
|
|
193
|
+
name: entry.name,
|
|
194
|
+
path: inner ? `public/${inner}/${entry.name}` : `public/${entry.name}`,
|
|
195
|
+
type: entry.type === 'directory' ? ('dir' as const) : ('file' as const),
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function hostWatch(listener: (event: ProjectFileEvent) => void): () => void {
|
|
200
|
+
const source = new EventSource(`${BASE}/events`);
|
|
201
|
+
const handler = (ev: MessageEvent) => {
|
|
202
|
+
try {
|
|
203
|
+
const data = JSON.parse(ev.data) as { type?: string; file?: string; path?: string };
|
|
204
|
+
const path = data.path ?? data.file;
|
|
205
|
+
if (!path) return;
|
|
206
|
+
listener({
|
|
207
|
+
type: (data.type as ProjectFileEvent['type']) ?? 'update',
|
|
208
|
+
path: normalize(path),
|
|
209
|
+
});
|
|
210
|
+
} catch {
|
|
211
|
+
// Non-JSON keepalive frame.
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
source.addEventListener('message', handler);
|
|
215
|
+
return () => {
|
|
216
|
+
source.removeEventListener('message', handler);
|
|
217
|
+
source.close();
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// ---------------------------------------------------------------------------
|
|
222
|
+
// The door
|
|
223
|
+
// ---------------------------------------------------------------------------
|
|
224
|
+
|
|
225
|
+
export const projectFiles = {
|
|
226
|
+
/** True while the workbench's own file service is answering. A caller with
|
|
227
|
+
* a transport of its own (the source-write lane) reads this to decide
|
|
228
|
+
* whether its write would be EXTERNAL to the workbench. */
|
|
229
|
+
frameOwned: filesProviderInstalled,
|
|
230
|
+
|
|
231
|
+
// Every door below `return await`s, never returns the promise bare. With a
|
|
232
|
+
// bare return this frame leaves V8's async stack, and a workbench file
|
|
233
|
+
// provider's rejection (`FileOperationError`) then carries ONLY workbench
|
|
234
|
+
// frames — the stack the console ledger reads to decide whether an error is
|
|
235
|
+
// the project's (`isWorkbenchOrigin`). A Play script's
|
|
236
|
+
// `await host.files.read('missing.json')` must keep its own frames on it.
|
|
237
|
+
async read(path: string): Promise<string> {
|
|
238
|
+
const key = assertContained(path);
|
|
239
|
+
return await (filesProvider()?.read(key) ?? hostRead(key));
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
async readBytes(path: string): Promise<Uint8Array> {
|
|
243
|
+
const key = assertContained(path);
|
|
244
|
+
const provider = filesProvider();
|
|
245
|
+
return await (provider?.readBytes ? provider.readBytes(key) : hostReadBytes(key));
|
|
246
|
+
},
|
|
247
|
+
|
|
248
|
+
async write(path: string, data: string | Uint8Array): Promise<void> {
|
|
249
|
+
const key = assertContained(path);
|
|
250
|
+
const provider = filesProvider();
|
|
251
|
+
if (provider) return await provider.write(key, data);
|
|
252
|
+
return await hostWrite(key, data);
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
async exists(path: string): Promise<boolean> {
|
|
256
|
+
const key = assertContained(path);
|
|
257
|
+
return await (filesProvider()?.exists(key) ?? hostExists(key));
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
async list(dir: string): Promise<readonly ProjectFileEntry[]> {
|
|
261
|
+
const key = assertContainedDir(dir);
|
|
262
|
+
const provider = filesProvider();
|
|
263
|
+
return await (provider?.list ? provider.list(key) : hostList(key));
|
|
264
|
+
},
|
|
265
|
+
|
|
266
|
+
watch(listener: (event: ProjectFileEvent) => void): () => void {
|
|
267
|
+
const provider = filesProvider();
|
|
268
|
+
return provider?.watch ? provider.watch(listener) : hostWatch(listener);
|
|
269
|
+
},
|
|
270
|
+
};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE FINDER NAMESPACE — host-owned discovery algorithms an adapter SELECTS.
|
|
3
|
+
*
|
|
4
|
+
* ARCHITECTURE-CORE §The editor protocol, "Zero inference": what zero
|
|
5
|
+
* inference forbids is the ENGINE running a finder nobody selected. A
|
|
6
|
+
* convention (`src/scenes/`, a story registration) is legitimate exactly when
|
|
7
|
+
* it is an adapter's declared finder parameter, and illegitimate as implicit
|
|
8
|
+
* engine behavior.
|
|
9
|
+
*
|
|
10
|
+
* That is enforced MECHANICALLY, not by policy: everything under this
|
|
11
|
+
* directory has exactly ONE sanctioned importer — the editor's adapter loader
|
|
12
|
+
* (`packages/sdk/src/kit/project-adapter.ts`) — and
|
|
13
|
+
* `packages/engine/test/finder-import-boundary.test.ts` fails by name when any
|
|
14
|
+
* other engine/editor file imports it. Do not add a second importer; make the
|
|
15
|
+
* loader answer instead.
|
|
16
|
+
*
|
|
17
|
+
* Dependency direction is one-way: finders import their parameter types from
|
|
18
|
+
* `../adapter-module`, and `adapter-module.ts` imports nothing from here. That
|
|
19
|
+
* is what keeps a game's `editor/volter.adapter.ts` free of finder implementations.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
EXPORTED_COMPOSITION_REGIONS,
|
|
24
|
+
type FinderSelection,
|
|
25
|
+
type ScenesFromEntrypointSelectionParams,
|
|
26
|
+
} from '@volter/project/adapter/adapter-module';
|
|
27
|
+
import type { FinderResult } from '@volter/project/adapter/finders/finder-result';
|
|
28
|
+
import { registerFinder, runRegisteredFinder } from '@volter/project/adapter/finders/registry';
|
|
29
|
+
import { type ZodType, z } from 'zod';
|
|
30
|
+
import {
|
|
31
|
+
type ScenesFromEntrypointSelectionInput,
|
|
32
|
+
scenesFromEntrypointSelection,
|
|
33
|
+
} from './scenes-from-entrypoint-selection';
|
|
34
|
+
|
|
35
|
+
export type { FinderResult } from '@volter/project/adapter/finders/finder-result';
|
|
36
|
+
export type {
|
|
37
|
+
FinderContribution,
|
|
38
|
+
FinderRegistration,
|
|
39
|
+
} from '@volter/project/adapter/finders/registry';
|
|
40
|
+
export {
|
|
41
|
+
finderReadsSources,
|
|
42
|
+
registerContributedFinder,
|
|
43
|
+
registeredFinderNames,
|
|
44
|
+
registerFinder,
|
|
45
|
+
runRegisteredFinder,
|
|
46
|
+
} from '@volter/project/adapter/finders/registry';
|
|
47
|
+
export type {
|
|
48
|
+
EntrypointSource,
|
|
49
|
+
ScenesFromEntrypointSelectionInput,
|
|
50
|
+
} from './scenes-from-entrypoint-selection';
|
|
51
|
+
export { scenesFromEntrypointSelection } from './scenes-from-entrypoint-selection';
|
|
52
|
+
|
|
53
|
+
/** Everything any shipped finder can be handed, gathered once by the loader. */
|
|
54
|
+
/** A project source the host read for a selection's `include` globs. */
|
|
55
|
+
export interface ProjectSourceFile {
|
|
56
|
+
/** Project-relative path. */
|
|
57
|
+
readonly path: string;
|
|
58
|
+
readonly source: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** One entry of the host's project component index. */
|
|
62
|
+
export interface ProjectComponentRef {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
/** Project-relative source path of the component's own module. */
|
|
65
|
+
readonly path: string;
|
|
66
|
+
/** Region this component's surface belongs to, when the host knows it. */
|
|
67
|
+
readonly region?: string | null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type FinderInput = ScenesFromEntrypointSelectionInput & {
|
|
71
|
+
/**
|
|
72
|
+
* The project's component index — what a finder joins its own discovery
|
|
73
|
+
* against (a prefab's source path and region).
|
|
74
|
+
*
|
|
75
|
+
* There is deliberately no `stories` here. `prefabsFromStories` used to be
|
|
76
|
+
* an engine finder whose story registrations the EDITOR filled, which is how
|
|
77
|
+
* the editor's adapter loader came to import the story registry and, through
|
|
78
|
+
* it, Storybook. It is a registered finder that reads its own ledger now
|
|
79
|
+
* (`packages/sdk/src/kit/stories/prefabs-finder.ts`): a finder's data arrives
|
|
80
|
+
* with the finder.
|
|
81
|
+
*/
|
|
82
|
+
readonly components?: readonly ProjectComponentRef[];
|
|
83
|
+
/** The sources matching every selection's `include` globs — empty when
|
|
84
|
+
* no selection declares any. A contributed finder reads the project
|
|
85
|
+
* through this and {@link FinderInput.files} and nothing else. */
|
|
86
|
+
readonly sources?: readonly ProjectSourceFile[];
|
|
87
|
+
/**
|
|
88
|
+
* The PATHS matching those same globs — every one of them, including the
|
|
89
|
+
* files `sources` has no text for.
|
|
90
|
+
*
|
|
91
|
+
* A finder over BINARY documents needs this and could not use `sources`:
|
|
92
|
+
* `@volter/editor-blender`'s `modelsFromBlendFiles` lists `.blend` files, and there
|
|
93
|
+
* is nothing in a `.blend` a text walk could honestly read — the entry IS
|
|
94
|
+
* the file. Handing it a decoded binary instead would have been the shim.
|
|
95
|
+
*/
|
|
96
|
+
readonly files?: readonly string[];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Run one adapter-declared selection. The switch is exhaustive over
|
|
101
|
+
* {@link FinderSelection}: a new finder that forgets a case fails to COMPILE
|
|
102
|
+
* here rather than silently contributing nothing.
|
|
103
|
+
*/
|
|
104
|
+
export function runFinderSelection(selection: FinderSelection, input: FinderInput): FinderResult {
|
|
105
|
+
return runRegisteredFinder(selection, input);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// The engine's own finders register here, schemas beside them: what an
|
|
109
|
+
// adapter may select by name is exactly what this registry holds.
|
|
110
|
+
const ScenesFromEntrypointSelectionSchema = z
|
|
111
|
+
.object({
|
|
112
|
+
finder: z.literal('scenesFromEntrypointSelection'),
|
|
113
|
+
regions: z
|
|
114
|
+
.union([z.array(z.string().min(1)).min(1), z.literal(EXPORTED_COMPOSITION_REGIONS)])
|
|
115
|
+
.describe('Region ids whose entrypoints carry the selection, or the rule form'),
|
|
116
|
+
selection: z
|
|
117
|
+
.string()
|
|
118
|
+
.min(1)
|
|
119
|
+
.optional()
|
|
120
|
+
.describe(
|
|
121
|
+
"Identifier of the entrypoint's module-level scene selection table; omit for a " +
|
|
122
|
+
'single-composition entrypoint',
|
|
123
|
+
),
|
|
124
|
+
})
|
|
125
|
+
.strict()
|
|
126
|
+
.refine((value) => value.selection === undefined || Array.isArray(value.regions), {
|
|
127
|
+
message:
|
|
128
|
+
'scenesFromEntrypointSelection: `selection` names an identifier in ONE entrypoint’s ' +
|
|
129
|
+
`source, so it cannot be paired with the \`${EXPORTED_COMPOSITION_REGIONS}\` rule — ` +
|
|
130
|
+
'name the region explicitly (`regions: ["<rootId>"]`).',
|
|
131
|
+
});
|
|
132
|
+
registerFinder<ScenesFromEntrypointSelectionParams, FinderInput>({
|
|
133
|
+
name: 'scenesFromEntrypointSelection',
|
|
134
|
+
schema:
|
|
135
|
+
ScenesFromEntrypointSelectionSchema as unknown as ZodType<ScenesFromEntrypointSelectionParams>,
|
|
136
|
+
run: scenesFromEntrypointSelection,
|
|
137
|
+
});
|