@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,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-backed `StorageBackend` for the local (Node) editor.
|
|
3
|
+
*
|
|
4
|
+
* A thin adapter over the editor server's existing routes — it changes nothing
|
|
5
|
+
* about how the local editor talks to disk, it just presents that surface behind
|
|
6
|
+
* the shared interface. The backend is rooted at the project's `public/` folder,
|
|
7
|
+
* matching the server's `/__editor/assets` (list) and `/__editor/save-file`
|
|
8
|
+
* (write) routes; reads come from Vite's `/@fs/` static serving.
|
|
9
|
+
*
|
|
10
|
+
* Route mapping (paths are relative to `public/`):
|
|
11
|
+
* list → GET /__editor/assets?dir → { entries: [{name,type,size,mtime}] }
|
|
12
|
+
* write → POST /__editor/save-file ({path, content, encoding?})
|
|
13
|
+
* read → GET /@fs/{projectRoot}/public/{path}
|
|
14
|
+
* watch → EventSource /__editor/events (chokidar-backed)
|
|
15
|
+
*
|
|
16
|
+
* The CLI control channel, native dialogs, `export`, online asset library, and
|
|
17
|
+
* project/editor-state persistence are NOT file operations and live outside this
|
|
18
|
+
* interface (see types.ts and editor-api.ts).
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { bytesToBase64 } from '../bytes-codec';
|
|
22
|
+
import { assertEditorServerAnswered, editorServerJson } from '../editor-server-response';
|
|
23
|
+
import { sourceMutationAttribution } from '../editor-session-attribution';
|
|
24
|
+
import { handleProjectMutationFailure } from '../source-conflict';
|
|
25
|
+
import { dirAndBase, normalize } from './paths';
|
|
26
|
+
import type { DirEntry, Stat, StorageBackend, WatchCallback, WatchEvent } from './types';
|
|
27
|
+
|
|
28
|
+
const BASE = '/__editor';
|
|
29
|
+
|
|
30
|
+
interface ServerAssetEntry {
|
|
31
|
+
name: string;
|
|
32
|
+
type: 'file' | 'directory';
|
|
33
|
+
size: number;
|
|
34
|
+
mtime: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export class HttpStorage implements StorageBackend {
|
|
38
|
+
readonly id = 'http';
|
|
39
|
+
|
|
40
|
+
/** Absolute project root on the server (used for /@fs reads). */
|
|
41
|
+
constructor(private readonly projectRoot: string) {}
|
|
42
|
+
|
|
43
|
+
async read(path: string): Promise<string> {
|
|
44
|
+
const res = await fetch(`/@fs/${this.projectRoot}/public/${normalize(path)}`);
|
|
45
|
+
if (!res.ok) throw new Error(`HttpStorage.read '${normalize(path)}': HTTP ${res.status}`);
|
|
46
|
+
return res.text();
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async readBytes(path: string): Promise<Uint8Array> {
|
|
50
|
+
const res = await fetch(`/@fs/${this.projectRoot}/public/${normalize(path)}`);
|
|
51
|
+
if (!res.ok) throw new Error(`HttpStorage.readBytes '${normalize(path)}': HTTP ${res.status}`);
|
|
52
|
+
return new Uint8Array(await res.arrayBuffer());
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async write(path: string, data: string | Uint8Array): Promise<void> {
|
|
56
|
+
const body =
|
|
57
|
+
typeof data === 'string'
|
|
58
|
+
? { path: normalize(path), content: data, ...sourceMutationAttribution() }
|
|
59
|
+
: {
|
|
60
|
+
path: normalize(path),
|
|
61
|
+
content: bytesToBase64(data),
|
|
62
|
+
encoding: 'base64' as const,
|
|
63
|
+
...sourceMutationAttribution(),
|
|
64
|
+
};
|
|
65
|
+
const res = await fetch(`${BASE}/save-file`, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: { 'Content-Type': 'application/json' },
|
|
68
|
+
body: JSON.stringify(body),
|
|
69
|
+
});
|
|
70
|
+
// This is the AUTOSAVE path. `!res.ok` alone let a page fallback report
|
|
71
|
+
// every save as written, so the editor kept showing saved work that no
|
|
72
|
+
// server had ever received.
|
|
73
|
+
assertEditorServerAnswered(res, `Write ${normalize(path)} failed`);
|
|
74
|
+
if (!res.ok) {
|
|
75
|
+
await handleProjectMutationFailure(res, {
|
|
76
|
+
label: `Write ${normalize(path)}`,
|
|
77
|
+
attempted: {
|
|
78
|
+
[`public/${normalize(path)}`]:
|
|
79
|
+
typeof data === 'string' ? data : `[${data.byteLength} binary bytes]`,
|
|
80
|
+
},
|
|
81
|
+
reapply: () => this.write(path, data),
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async writeIfAbsent(path: string, data: string | Uint8Array): Promise<boolean> {
|
|
87
|
+
// Browser adaptation never uses HttpStorage: the Node endpoint owns its
|
|
88
|
+
// true `wx` write. Keep the interface honest for generic callers.
|
|
89
|
+
if (await this.exists(path)) return false;
|
|
90
|
+
await this.write(path, data);
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async list(dir: string): Promise<DirEntry[]> {
|
|
95
|
+
const res = await fetch(`${BASE}/assets?${new URLSearchParams({ dir: normalize(dir) })}`);
|
|
96
|
+
const { entries } = await editorServerJson<{ entries: ServerAssetEntry[] }>(
|
|
97
|
+
res,
|
|
98
|
+
`HttpStorage.list '${normalize(dir)}' failed`,
|
|
99
|
+
);
|
|
100
|
+
return entries.map((e) => {
|
|
101
|
+
const out: DirEntry = {
|
|
102
|
+
name: e.name,
|
|
103
|
+
path: normalize(dir ? `${dir}/${e.name}` : e.name),
|
|
104
|
+
type: e.type === 'directory' ? 'dir' : 'file',
|
|
105
|
+
mtime: e.mtime,
|
|
106
|
+
};
|
|
107
|
+
if (e.type === 'file') out.size = e.size;
|
|
108
|
+
out.mtime = e.mtime;
|
|
109
|
+
return out;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async stat(path: string): Promise<Stat | null> {
|
|
114
|
+
// The server exposes listings, not a per-path stat. Derive from the parent
|
|
115
|
+
// listing — sufficient for the editor's needs (existence + type + size).
|
|
116
|
+
const [dir, base] = dirAndBase(path);
|
|
117
|
+
if (!base) return { path: '', type: 'dir', size: 0, mtime: 0 };
|
|
118
|
+
let entries: DirEntry[];
|
|
119
|
+
try {
|
|
120
|
+
entries = await this.list(dir);
|
|
121
|
+
} catch {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
const hit = entries.find((e) => e.name === base);
|
|
125
|
+
return hit
|
|
126
|
+
? { path: hit.path, type: hit.type, size: hit.size ?? 0, mtime: hit.mtime ?? 0 }
|
|
127
|
+
: null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
async exists(path: string): Promise<boolean> {
|
|
131
|
+
return (await this.stat(path)) !== null;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
async mkdir(path: string): Promise<void> {
|
|
135
|
+
// The server has no empty-dir route; directories materialize when their
|
|
136
|
+
// first file is written (save-file creates parents). No-op here.
|
|
137
|
+
void path;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async remove(path: string): Promise<void> {
|
|
141
|
+
const res = await fetch(`${BASE}/save-file`, {
|
|
142
|
+
method: 'POST',
|
|
143
|
+
headers: { 'Content-Type': 'application/json' },
|
|
144
|
+
body: JSON.stringify({ path: normalize(path), delete: true, ...sourceMutationAttribution() }),
|
|
145
|
+
});
|
|
146
|
+
assertEditorServerAnswered(res, `Delete ${normalize(path)} failed`);
|
|
147
|
+
if (!res.ok) {
|
|
148
|
+
await handleProjectMutationFailure(res, {
|
|
149
|
+
label: `Delete ${normalize(path)}`,
|
|
150
|
+
attempted: { [`public/${normalize(path)}`]: null },
|
|
151
|
+
reapply: () => this.remove(path),
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
watch(callback: WatchCallback): () => void {
|
|
157
|
+
const source = new EventSource(`${BASE}/events`);
|
|
158
|
+
const handler = (ev: MessageEvent) => {
|
|
159
|
+
try {
|
|
160
|
+
const data = JSON.parse(ev.data) as { type?: string; file?: string; path?: string };
|
|
161
|
+
const path = data.path ?? data.file;
|
|
162
|
+
if (!path) return;
|
|
163
|
+
callback({ type: (data.type as WatchEvent['type']) ?? 'update', path: normalize(path) });
|
|
164
|
+
} catch {
|
|
165
|
+
// Ignore non-JSON keepalive frames.
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
source.addEventListener('message', handler);
|
|
169
|
+
return () => {
|
|
170
|
+
source.removeEventListener('message', handler);
|
|
171
|
+
source.close();
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage backend selection — the `public/`-rooted file interface the editor's
|
|
3
|
+
* asset surfaces read and write through.
|
|
4
|
+
*
|
|
5
|
+
* ONE TIER, two implementations, and the second is a decorator:
|
|
6
|
+
* - `HttpStorage` — the session's own `/__editor/*` routes.
|
|
7
|
+
* - `HostFilesStorage` — the same view, written through `EditorHost.files`
|
|
8
|
+
* so a write is the WORKBENCH's own (U5).
|
|
9
|
+
* `MemStorage` is the design system's fixture backend and nothing else.
|
|
10
|
+
*
|
|
11
|
+
* Upstream code depends only on `StorageBackend` from `./types` and obtains
|
|
12
|
+
* an instance via `getStorageBackend()`.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { getProjectDefinePath } from '../editor-mode';
|
|
16
|
+
import { filesProviderInstalled } from '../files/file-provider';
|
|
17
|
+
import { HostFilesStorage } from './host-files-storage';
|
|
18
|
+
import { HttpStorage } from './http-storage';
|
|
19
|
+
import type { StorageBackend } from './types';
|
|
20
|
+
|
|
21
|
+
export { HttpStorage } from './http-storage';
|
|
22
|
+
export { MemStorage } from './mem-storage';
|
|
23
|
+
export type { DirEntry, HostCapabilities, Stat, StorageBackend, WatchEvent } from './types';
|
|
24
|
+
|
|
25
|
+
let _backend: StorageBackend | null = null;
|
|
26
|
+
/** The tier's own backend, kept beside the active one so the frame decorator
|
|
27
|
+
* never becomes its own delegate — see {@link tierStorageBackend}. */
|
|
28
|
+
let _tier: StorageBackend | null = null;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* THE TIER'S OWN backend — never the frame decorator, and the only thing the
|
|
32
|
+
* file door's host fill is allowed to stand on.
|
|
33
|
+
*
|
|
34
|
+
* Without this the fill would recurse: `projectFiles.read` falls back to
|
|
35
|
+
* `getStorageBackend()`, which under the frame is `HostFilesStorage`, whose
|
|
36
|
+
* `read` is `projectFiles.read`. One function, so the cycle cannot be written
|
|
37
|
+
* by accident.
|
|
38
|
+
*/
|
|
39
|
+
export function tierStorageBackend(): StorageBackend {
|
|
40
|
+
if (_backend && !(_backend instanceof HostFilesStorage)) return _backend;
|
|
41
|
+
if (!_tier) _tier = new HttpStorage(getProjectDefinePath());
|
|
42
|
+
return _tier;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The active storage backend: the session's own, wrapped by the frame's file
|
|
47
|
+
* door once its provider has landed.
|
|
48
|
+
*
|
|
49
|
+
* UNDER THE CODE-OSS FRAME the file system is the WORKBENCH'S, not the
|
|
50
|
+
* session's (U5; ARCHITECTURE-CORE §The core is Code-OSS, "the storage
|
|
51
|
+
* backends → file system providers"). `HostFilesStorage` is the `public/`
|
|
52
|
+
* view onto `EditorHost.files`, so an asset write is the workbench's own write
|
|
53
|
+
* on the URI it already holds — the same property that closed U4's redo open
|
|
54
|
+
* for source files. Everything the file door does not carry (remove, mkdir,
|
|
55
|
+
* stat, list, watch) stays this tier's, which is why the decorator keeps it
|
|
56
|
+
* rather than replacing it.
|
|
57
|
+
*
|
|
58
|
+
* Read at FIRST USE rather than at module load: the bridge takes ownership
|
|
59
|
+
* before the editor mounts, but the provider arrives with the contribution's
|
|
60
|
+
* own services, after — see `files/file-provider.ts`.
|
|
61
|
+
*/
|
|
62
|
+
export function getStorageBackend(): StorageBackend {
|
|
63
|
+
if (_backend) return _backend;
|
|
64
|
+
const tier = tierStorageBackend();
|
|
65
|
+
_backend = filesProviderInstalled() ? new HostFilesStorage(tier) : tier;
|
|
66
|
+
return _backend;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Override the active backend (the design system's fixture). */
|
|
70
|
+
export function setStorageBackend(backend: StorageBackend): void {
|
|
71
|
+
_backend = backend;
|
|
72
|
+
// An explicitly installed backend REPLACES the tier, so the file door's host
|
|
73
|
+
// fill stands on it too rather than on a stale one it would otherwise hold.
|
|
74
|
+
if (!(backend instanceof HostFilesStorage)) _tier = backend;
|
|
75
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure in-memory `StorageBackend` — a virtual filesystem backed by a `Map`.
|
|
3
|
+
*
|
|
4
|
+
* Nothing touches disk; files live as bytes in JS and vanish on reload. The
|
|
5
|
+
* most "virtual" of the backends, and the simplest — the design system's
|
|
6
|
+
* fixture (`design-system-stories/fixtures/editor-runtime.tsx`) is what uses
|
|
7
|
+
* it: a story needs a project-shaped backend and must write nothing.
|
|
8
|
+
*
|
|
9
|
+
* Implements the same interface as every other backend, so it is a drop-in via
|
|
10
|
+
* `setStorageBackend(new MemStorage())`.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { dirAndBase, normalize } from './paths';
|
|
14
|
+
import type { DirEntry, Stat, StorageBackend, WatchCallback, WatchEvent } from './types';
|
|
15
|
+
|
|
16
|
+
type Node = { type: 'file'; data: Uint8Array; mtime: number } | { type: 'dir'; mtime: number };
|
|
17
|
+
|
|
18
|
+
export class MemStorage implements StorageBackend {
|
|
19
|
+
readonly id = 'mem';
|
|
20
|
+
|
|
21
|
+
/** Normalized path → node. The root (`''`) is implicit. */
|
|
22
|
+
private readonly nodes = new Map<string, Node>();
|
|
23
|
+
private readonly watchers = new Set<WatchCallback>();
|
|
24
|
+
|
|
25
|
+
/** Optionally seed the VFS from a `{ path: contents }` map. */
|
|
26
|
+
constructor(seed?: Record<string, string | Uint8Array>) {
|
|
27
|
+
if (seed) for (const [path, data] of Object.entries(seed)) this.writeSync(path, data);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private emit(event: WatchEvent): void {
|
|
31
|
+
for (const cb of this.watchers) cb(event);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Ensure every ancestor directory of `path` exists. */
|
|
35
|
+
private ensureParents(path: string): void {
|
|
36
|
+
const parts = normalize(path).split('/');
|
|
37
|
+
parts.pop();
|
|
38
|
+
let cur = '';
|
|
39
|
+
for (const part of parts) {
|
|
40
|
+
cur = cur ? `${cur}/${part}` : part;
|
|
41
|
+
if (this.nodes.get(cur)?.type !== 'dir') this.nodes.set(cur, { type: 'dir', mtime: now() });
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private writeSync(path: string, data: string | Uint8Array): boolean {
|
|
46
|
+
const norm = normalize(path);
|
|
47
|
+
this.ensureParents(norm);
|
|
48
|
+
const existed = this.nodes.get(norm)?.type === 'file';
|
|
49
|
+
const bytes = typeof data === 'string' ? new TextEncoder().encode(data) : new Uint8Array(data);
|
|
50
|
+
this.nodes.set(norm, { type: 'file', data: bytes, mtime: now() });
|
|
51
|
+
return existed;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async read(path: string): Promise<string> {
|
|
55
|
+
return new TextDecoder().decode(await this.readBytes(path));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async readBytes(path: string): Promise<Uint8Array> {
|
|
59
|
+
const node = this.nodes.get(normalize(path));
|
|
60
|
+
if (node?.type !== 'file')
|
|
61
|
+
throw new Error(`MemStorage.read: no such file '${normalize(path)}'`);
|
|
62
|
+
// Reads own their bytes, just like File/HTTP backends. Asset serving
|
|
63
|
+
// transfers this buffer to a worker; sharing the stored buffer would
|
|
64
|
+
// detach the file itself and break every subsequent read.
|
|
65
|
+
return node.data.slice();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async write(path: string, data: string | Uint8Array): Promise<void> {
|
|
69
|
+
const existed = this.writeSync(path, data);
|
|
70
|
+
this.emit({ type: existed ? 'update' : 'create', path: normalize(path) });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async writeIfAbsent(path: string, data: string | Uint8Array): Promise<boolean> {
|
|
74
|
+
if (await this.exists(path)) return false;
|
|
75
|
+
this.writeSync(path, data);
|
|
76
|
+
this.emit({ type: 'create', path: normalize(path) });
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
async list(dir: string): Promise<DirEntry[]> {
|
|
81
|
+
const dn = normalize(dir);
|
|
82
|
+
if (dn !== '' && this.nodes.get(dn)?.type !== 'dir') {
|
|
83
|
+
throw new Error(`MemStorage.list: no such directory '${dn}'`);
|
|
84
|
+
}
|
|
85
|
+
const entries: DirEntry[] = [];
|
|
86
|
+
for (const [path, node] of this.nodes) {
|
|
87
|
+
const [parent, base] = dirAndBase(path);
|
|
88
|
+
if (parent !== dn || !base) continue;
|
|
89
|
+
const entry: DirEntry = {
|
|
90
|
+
name: base,
|
|
91
|
+
path,
|
|
92
|
+
type: node.type === 'dir' ? 'dir' : 'file',
|
|
93
|
+
mtime: node.mtime,
|
|
94
|
+
};
|
|
95
|
+
if (node.type === 'file') entry.size = node.data.length;
|
|
96
|
+
entry.mtime = node.mtime;
|
|
97
|
+
entries.push(entry);
|
|
98
|
+
}
|
|
99
|
+
entries.sort((a, b) => {
|
|
100
|
+
if (a.type !== b.type) return a.type === 'dir' ? -1 : 1;
|
|
101
|
+
return a.name.localeCompare(b.name);
|
|
102
|
+
});
|
|
103
|
+
return entries;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async stat(path: string): Promise<Stat | null> {
|
|
107
|
+
const norm = normalize(path);
|
|
108
|
+
if (norm === '') return { path: '', type: 'dir', size: 0, mtime: 0 };
|
|
109
|
+
const node = this.nodes.get(norm);
|
|
110
|
+
if (!node) return null;
|
|
111
|
+
return node.type === 'file'
|
|
112
|
+
? { path: norm, type: 'file', size: node.data.length, mtime: node.mtime }
|
|
113
|
+
: { path: norm, type: 'dir', size: 0, mtime: node.mtime };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
async exists(path: string): Promise<boolean> {
|
|
117
|
+
return (await this.stat(path)) !== null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
async mkdir(path: string): Promise<void> {
|
|
121
|
+
const norm = normalize(path);
|
|
122
|
+
if (!norm || this.nodes.get(norm)?.type === 'dir') return;
|
|
123
|
+
this.ensureParents(norm);
|
|
124
|
+
this.nodes.set(norm, { type: 'dir', mtime: now() });
|
|
125
|
+
this.emit({ type: 'create', path: norm });
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async remove(path: string): Promise<void> {
|
|
129
|
+
const norm = normalize(path);
|
|
130
|
+
if (!norm) return;
|
|
131
|
+
let removed = false;
|
|
132
|
+
for (const key of [...this.nodes.keys()]) {
|
|
133
|
+
if (key === norm || key.startsWith(`${norm}/`)) {
|
|
134
|
+
this.nodes.delete(key);
|
|
135
|
+
removed = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (removed) this.emit({ type: 'remove', path: norm });
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
watch(callback: WatchCallback): () => void {
|
|
142
|
+
this.watchers.add(callback);
|
|
143
|
+
return () => this.watchers.delete(callback);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function now(): number {
|
|
148
|
+
return Date.now();
|
|
149
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one cross-realm mutual exclusion a browser storage backend has:
|
|
3
|
+
* `navigator.locks`, keyed by backend id + path.
|
|
4
|
+
*
|
|
5
|
+
* Two callers matter and they MUST agree on the name, which is why this is a
|
|
6
|
+
* shared function rather than a string built at each site — and why the name is
|
|
7
|
+
* derived from the NORMALIZED path here rather than from whatever each caller
|
|
8
|
+
* happens to hold. Sharing the function is not enough on its own: one caller
|
|
9
|
+
* passes an already-normalized path and the other passes a module constant, so
|
|
10
|
+
* agreement used to rest on that constant being spelled in normalized form.
|
|
11
|
+
* Respell it as `/.vgai/assets.json` and the two names diverge, both locks are
|
|
12
|
+
* "held", and mutual exclusion is silently gone with nothing failing. Deriving
|
|
13
|
+
* the name from `normalize()` makes the agreement structural.
|
|
14
|
+
*
|
|
15
|
+
* Callers:
|
|
16
|
+
* - the asset ledger's `.lock` compare-and-delete
|
|
17
|
+
* (`../asset-workflow/asset-ledger-backend.ts`) — several steps that must
|
|
18
|
+
* not interleave with each other OR with the create above.
|
|
19
|
+
*
|
|
20
|
+
* Scope, stated exactly: Web Locks span every same-origin realm — the two
|
|
21
|
+
* tabs on one project that motivate the ledger lock in the first place — and
|
|
22
|
+
* nothing else. A writer that is not same-origin JS (a Node process
|
|
23
|
+
* reaching the same files, i.e. `HttpStorage` racing the CLI) is not serialized
|
|
24
|
+
* by this, and cannot be from the browser side.
|
|
25
|
+
*
|
|
26
|
+
* Absent in a non-secure context and in Node (tests): callers then get the bare
|
|
27
|
+
* operation, which is the same exclusivity the platform itself offers.
|
|
28
|
+
*/
|
|
29
|
+
import { normalize } from './paths';
|
|
30
|
+
|
|
31
|
+
export function withPathLock<T>(
|
|
32
|
+
backendId: string,
|
|
33
|
+
path: string,
|
|
34
|
+
operation: () => Promise<T>,
|
|
35
|
+
): Promise<T> {
|
|
36
|
+
const locks = globalThis.navigator?.locks;
|
|
37
|
+
if (!locks) return operation();
|
|
38
|
+
// `LockManager.request`'s DOM typing infers its result from the callback's
|
|
39
|
+
// literal return type (`(lock) => T`), so an async callback types as
|
|
40
|
+
// `Promise<Promise<T>>`. The platform awaits the returned promise before
|
|
41
|
+
// releasing the lock — that flattening is the documented behavior, not an
|
|
42
|
+
// assumption — so the settled value really is `T`.
|
|
43
|
+
return locks.request(`vgai:${backendId}:${normalize(path)}`, operation) as Promise<T>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path helpers for storage backends. Paths are POSIX-style, root-relative,
|
|
3
|
+
* '/'-separated, with no leading/trailing slashes.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** Split a path into non-empty segments, collapsing `.` and redundant slashes. */
|
|
7
|
+
export function segments(path: string): string[] {
|
|
8
|
+
return path.split('/').filter((s) => s.length > 0 && s !== '.');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
/** Normalize to a canonical root-relative path (`''` for the root). */
|
|
12
|
+
export function normalize(path: string): string {
|
|
13
|
+
return segments(path).join('/');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Split into `[parentDir, baseName]`. Root entries have `parent === ''`. */
|
|
17
|
+
export function dirAndBase(path: string): [string, string] {
|
|
18
|
+
const segs = segments(path);
|
|
19
|
+
const base = segs.pop() ?? '';
|
|
20
|
+
return [segs.join('/'), base];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Join path parts into a normalized path. */
|
|
24
|
+
export function join(...parts: string[]): string {
|
|
25
|
+
return normalize(parts.join('/'));
|
|
26
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Backend-agnostic file interface for the editor.
|
|
3
|
+
*
|
|
4
|
+
* The editor and engine read/write project files through one `StorageBackend`
|
|
5
|
+
* and never learn which implementation is behind it — the session's own
|
|
6
|
+
* `/__editor/*` routes, the frame's file door over them, or the design
|
|
7
|
+
* system's in-memory fixture.
|
|
8
|
+
*
|
|
9
|
+
* Scope — this interface deliberately covers ONLY what reduces to file
|
|
10
|
+
* operations. Three editor concerns do not, and are handled elsewhere:
|
|
11
|
+
* - native folder dialogs / "reveal in OS file manager" → `HostCapabilities`
|
|
12
|
+
* - the `vgai` CLI control channel (SSE + command RPC) → server-only, dropped
|
|
13
|
+
* in a pure-browser editor
|
|
14
|
+
* - `export` / packaging (spawns a build) → a client-side bundler in-browser
|
|
15
|
+
*
|
|
16
|
+
* `watch` is part of the interface but its semantics are backend-specific: a
|
|
17
|
+
* server backend reports real filesystem events (chokidar); a browser backend
|
|
18
|
+
* has no OS file-change notifications, so it derives events from its OWN writes
|
|
19
|
+
* (in a server-less editor the editor is the only writer — which is exactly the
|
|
20
|
+
* signal HMR needs).
|
|
21
|
+
*
|
|
22
|
+
* Paths are POSIX-style, project-root-relative, '/'-separated, no leading slash
|
|
23
|
+
* (e.g. `src/scripts/components/spin.ts`).
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
export type NodeType = 'file' | 'dir';
|
|
27
|
+
|
|
28
|
+
export interface Stat {
|
|
29
|
+
/** Normalized, root-relative path. */
|
|
30
|
+
path: string;
|
|
31
|
+
type: NodeType;
|
|
32
|
+
/** Byte length for files; 0 for directories. */
|
|
33
|
+
size: number;
|
|
34
|
+
/** Last-modified time, epoch ms (0 if the backend cannot report it). */
|
|
35
|
+
mtime: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface DirEntry {
|
|
39
|
+
/** Base name (no slashes). */
|
|
40
|
+
name: string;
|
|
41
|
+
/** Normalized, root-relative path. */
|
|
42
|
+
path: string;
|
|
43
|
+
type: NodeType;
|
|
44
|
+
/** Byte length for files (omitted for directories). */
|
|
45
|
+
size?: number;
|
|
46
|
+
/** Last-modified time, epoch ms (omitted if the backend cannot report it). */
|
|
47
|
+
mtime?: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type WatchEventType = 'create' | 'update' | 'remove';
|
|
51
|
+
|
|
52
|
+
export interface WatchEvent {
|
|
53
|
+
type: WatchEventType;
|
|
54
|
+
/** Normalized, root-relative path of the affected node. */
|
|
55
|
+
path: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export type WatchCallback = (event: WatchEvent) => void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The one file interface every storage backend implements. All methods take and
|
|
62
|
+
* return normalized, root-relative POSIX paths.
|
|
63
|
+
*/
|
|
64
|
+
export interface StorageBackend {
|
|
65
|
+
/** Stable identifier for the active backend (for diagnostics/feature flags). */
|
|
66
|
+
readonly id: string;
|
|
67
|
+
|
|
68
|
+
/** Read a UTF-8 text file. Rejects if the path is missing or is a directory. */
|
|
69
|
+
read(path: string): Promise<string>;
|
|
70
|
+
/** Read raw bytes. Rejects if the path is missing or is a directory. */
|
|
71
|
+
readBytes(path: string): Promise<Uint8Array>;
|
|
72
|
+
|
|
73
|
+
/** Write a file, creating parent directories as needed. Emits a watch event. */
|
|
74
|
+
write(path: string, data: string | Uint8Array): Promise<void>;
|
|
75
|
+
/**
|
|
76
|
+
* Create a new file without replacing an existing one. Returns false when
|
|
77
|
+
* the path already exists. Browser handle APIs have no OS-level O_EXCL;
|
|
78
|
+
* HandleStorage serializes same-origin writers and rechecks at handle
|
|
79
|
+
* acquisition, while an external process may still win the final race.
|
|
80
|
+
*/
|
|
81
|
+
writeIfAbsent(path: string, data: string | Uint8Array): Promise<boolean>;
|
|
82
|
+
|
|
83
|
+
/** Shallow directory listing. Rejects if the path is missing or is a file. */
|
|
84
|
+
list(dir: string): Promise<DirEntry[]>;
|
|
85
|
+
|
|
86
|
+
/** Stat a node, or resolve to `null` if it does not exist. */
|
|
87
|
+
stat(path: string): Promise<Stat | null>;
|
|
88
|
+
|
|
89
|
+
/** Convenience existence check. */
|
|
90
|
+
exists(path: string): Promise<boolean>;
|
|
91
|
+
|
|
92
|
+
/** Recursively create a directory (no-op if it already exists). */
|
|
93
|
+
mkdir(path: string): Promise<void>;
|
|
94
|
+
|
|
95
|
+
/** Recursively remove a file or directory (no-op if missing). Emits an event. */
|
|
96
|
+
remove(path: string): Promise<void>;
|
|
97
|
+
|
|
98
|
+
/** Subscribe to change events. Returns an unsubscribe function. */
|
|
99
|
+
watch(callback: WatchCallback): () => void;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Non-file host capabilities, kept separate from `StorageBackend` because they
|
|
104
|
+
* do not reduce to path operations. A backend may implement none of these.
|
|
105
|
+
*/
|
|
106
|
+
export interface HostCapabilities {
|
|
107
|
+
/**
|
|
108
|
+
* Prompt the user to choose a project root and return a backend rooted there.
|
|
109
|
+
* Browser: `showDirectoryPicker()` (Chromium). Resolves to `null` if the user
|
|
110
|
+
* cancels. Absent entirely where unsupported.
|
|
111
|
+
*/
|
|
112
|
+
pickProjectRoot?(): Promise<StorageBackend | null>;
|
|
113
|
+
|
|
114
|
+
/** Reveal a path in the OS file manager. Absent in the browser. */
|
|
115
|
+
reveal?(path: string): Promise<void>;
|
|
116
|
+
}
|