@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,827 @@
|
|
|
1
|
+
// C3 (phase-b/c3-r3f-packaged) — the adaptive `optimizeDeps.entries` source
|
|
2
|
+
// for `packaged.ts`'s project-rooted Vite instance. See that file's header
|
|
3
|
+
// doc comment, "optimizeDeps" section, for the full crawl-vs-crash story;
|
|
4
|
+
// this module only computes WHICH files to scope the crawl to.
|
|
5
|
+
|
|
6
|
+
import { type Dirent, existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
|
|
7
|
+
import { createRequire } from 'node:module';
|
|
8
|
+
import { dirname, isAbsolute, join, relative, sep } from 'node:path';
|
|
9
|
+
import { EDITOR_LANE_DIRS } from '@volter/editor-sdk/session/tool-contribution-convention';
|
|
10
|
+
import { isDynamicPattern } from 'tinyglobby';
|
|
11
|
+
import { loadGameManifestDir } from '@volter/editor-project/manifest/load-file';
|
|
12
|
+
import { doorwayModuleSource, PACKAGED_MODULE_DOORWAYS } from '../vite-plugin-module-doorways';
|
|
13
|
+
import { isToolContributionModule, projectStorySourceDirs } from './server-utils';
|
|
14
|
+
import { ADAPTER_MODULE_FILENAME } from '../src/ui-source/adapter-region-includes';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* SERVER-ONLY packages that must never be crawled INTO during the client
|
|
18
|
+
* dep-prebundle — passed to `optimizeDeps.exclude` in `packaged.ts` (C3
|
|
19
|
+
* hardening follow-on). Belt to the entries-scoping suspenders.
|
|
20
|
+
*
|
|
21
|
+
* ## The pathological case this closes
|
|
22
|
+
*
|
|
23
|
+
* The entries-scoping fix (`computeProjectOptimizeDepsEntries` below) makes
|
|
24
|
+
* the crawl start ONLY from a project's declared world entries — which
|
|
25
|
+
* NORMALLY never reach `server/` code, so the colyseus server stack
|
|
26
|
+
* (`colyseus` -> `@colyseus/core` -> `@pm2/io`) is never crawled and the
|
|
27
|
+
* esbuild-scanner crash that `noDiscovery: true` used to guard against never
|
|
28
|
+
* fires. But if a project VIOLATES the repo's D2 rule (CLAUDE.md
|
|
29
|
+
* "Networking": client code calls Colyseus via the CLIENT SDK
|
|
30
|
+
* `@colyseus/sdk`, dynamic-imported, and NEVER value-imports the `server/`
|
|
31
|
+
* room classes) by having a WORLD ENTRY statically `import` from `server/`,
|
|
32
|
+
* the crawl reaches `@colyseus/core`'s `Stats.mjs`, whose `import("@pm2/io")`
|
|
33
|
+
* has no resolvable browser entry, and esbuild's prebundle step THROWS from
|
|
34
|
+
* inside the async optimizer — which, unhandled, HARD-KILLS the whole
|
|
35
|
+
* packaged node process (the only authoring surface). That is a strictly
|
|
36
|
+
* harsher degrade than the old `noDiscovery: true`, which at least still
|
|
37
|
+
* booted an editor.
|
|
38
|
+
*
|
|
39
|
+
* `exclude`-ing these three names keeps esbuild from crawling into them
|
|
40
|
+
* during prebundle: even a world entry that (wrongly) reaches them no longer
|
|
41
|
+
* crashes the scanner — the offending world degrades to a benign browser-
|
|
42
|
+
* side runtime import failure for that ONE world, and the editor process
|
|
43
|
+
* survives and serves everything else. Verified live (a real, checkout-
|
|
44
|
+
* absent packaged boot against a project whose world entry value-imports
|
|
45
|
+
* `server/rooms`): without this list the server process dies at boot; with
|
|
46
|
+
* it, the server boots and serves.
|
|
47
|
+
*
|
|
48
|
+
* CRITICAL: this list must NOT contain `@colyseus/sdk` — that is the
|
|
49
|
+
* legitimate CLIENT SDK a real multiplayer project's own game code imports
|
|
50
|
+
* (dynamic-imported per D2; e.g. `examples/third-person-arena/src/
|
|
51
|
+
* network.ts`). It is a SEPARATE package from `@colyseus/core` — its own
|
|
52
|
+
* published `build/index.mjs` is a self-contained client bundle — and MUST
|
|
53
|
+
* still prebundle so those projects work. Excluding only the server-side
|
|
54
|
+
* names leaves the client SDK's prebundle path untouched (proven: a world
|
|
55
|
+
* entry importing `@colyseus/sdk` still prebundles it cleanly with this
|
|
56
|
+
* exclude list active).
|
|
57
|
+
*/
|
|
58
|
+
export const SERVER_ONLY_PREBUNDLE_EXCLUDE: readonly string[] = [
|
|
59
|
+
'colyseus',
|
|
60
|
+
'@colyseus/core',
|
|
61
|
+
'@pm2/io',
|
|
62
|
+
];
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The project-relative runtime WORLD entries shared by dependency discovery
|
|
66
|
+
* and source warmup, for the project rooted at
|
|
67
|
+
* `projectRoot` — every `roots[].entry` its OWN `vgai.project.json` declares
|
|
68
|
+
* (default-adapter, code-authored roots; scene-only roots have no `entry`
|
|
69
|
+
* and contribute nothing here — their gameplay code is registered
|
|
70
|
+
* elsewhere, reached transitively from whichever world DOES declare an
|
|
71
|
+
* `entry`, e.g. the template's single world), deduped, and filtered to paths
|
|
72
|
+
* that exist on disk.
|
|
73
|
+
*
|
|
74
|
+
* ## Why THESE files, not `index.html` or the project's own bootstrap `main.ts`
|
|
75
|
+
*
|
|
76
|
+
* A project's `index.html` -> `src/main.ts` bootstrap ties every declared
|
|
77
|
+
* world together for the STANDALONE (`npm run game`) build, and — critically
|
|
78
|
+
* — the scaffolded template's own `main.ts` also carries the P2P-Colyseus
|
|
79
|
+
* URL-param branch that dynamically imports the project's OWN `server/rooms`
|
|
80
|
+
* (`await import('../server/rooms')`, gated behind `?net=p2p-host`, but
|
|
81
|
+
* esbuild's dependency scanner follows a string-literal dynamic `import()`
|
|
82
|
+
* as an unconditional graph edge regardless of the runtime guard around it).
|
|
83
|
+
* `server/rooms.ts` re-exports real Colyseus `Room` classes, whose `colyseus`
|
|
84
|
+
* (SERVER package) import chain reaches `@colyseus/core` -> `@pm2/io`, a
|
|
85
|
+
* package esbuild's prebundle step cannot resolve an entry for (confirmed
|
|
86
|
+
* empirically, not theoretically: a direct `vite.optimizeDeps` run scoped to
|
|
87
|
+
* `index.html`-style discovery against `packages/editor/template` throws
|
|
88
|
+
* `Failed to resolve entry for package "@pm2/io"` from inside
|
|
89
|
+
* `@colyseus/core/build/Stats.mjs`'s own `import("@pm2/io")` — this is
|
|
90
|
+
* `packaged.ts`'s ORIGINAL reason for `noDiscovery: true`, verified still
|
|
91
|
+
* true on this Vite version at the time of the C3 fix).
|
|
92
|
+
*
|
|
93
|
+
* A manifest's `roots[].entry` files never reach that chain: they are the
|
|
94
|
+
* PER-WORLD mount code the editor's own binding-resolver dynamically imports
|
|
95
|
+
* directly for Play mode / world mounting (never `src/main.ts` — that
|
|
96
|
+
* bootstrap is the STANDALONE build's concern, unrelated to how the editor
|
|
97
|
+
* itself mounts a world; see `packaged.ts`'s header doc comment). Scoping the
|
|
98
|
+
* crawl to exactly these files means: (a) it never touches `server/`, so the
|
|
99
|
+
* `@pm2/io` class of crash cannot occur no matter what a project's server
|
|
100
|
+
* room code imports, and (b) any CJS-needing-prebundle client dependency a
|
|
101
|
+
* world's own code reaches — `react`, `@react-three/fiber`, `@react-three/
|
|
102
|
+
* drei`, or some future ecosystem this repo has never heard of — gets
|
|
103
|
+
* auto-discovered and prebundled for free, with no per-package allowlist to
|
|
104
|
+
* maintain (this is what actually fixes the R3F class of bug this file's own
|
|
105
|
+
* feature exists for: `@react-three/fiber`'s CJS transitive deps like
|
|
106
|
+
* `use-sync-external-store` are reached from `examples/r3f-first-party`'s
|
|
107
|
+
* `src/net-entry.tsx`, never from anything server-shaped).
|
|
108
|
+
*
|
|
109
|
+
* The client SDK case (`@colyseus/sdk`, the package a world's own game code
|
|
110
|
+
* legitimately imports for real multiplayer — e.g.
|
|
111
|
+
* `examples/third-person-arena/src/network.ts`) is DIFFERENT from the
|
|
112
|
+
* server-package case above and does NOT crash: `@colyseus/sdk`'s own
|
|
113
|
+
* published build (`build/index.mjs`) is a self-contained client bundle that
|
|
114
|
+
* does not pull in `@colyseus/core`'s server-only `Stats.mjs` (confirmed
|
|
115
|
+
* empirically the same way: a full prebundle scoped to
|
|
116
|
+
* `examples/third-person-arena`'s own `src/index.tsx` world entry succeeds
|
|
117
|
+
* and prebundles `@colyseus/sdk` cleanly).
|
|
118
|
+
*
|
|
119
|
+
* ## Discovery and warmup lifetimes
|
|
120
|
+
*
|
|
121
|
+
* Dependency discovery computes this ONCE from the boot-time `VGAI_PROJECT`,
|
|
122
|
+
* exactly like `engineSrc`/`resolve.alias` in `packaged.ts`; those settings
|
|
123
|
+
* are baked into Vite's `createServer` call. Checkout-dev source warmup also
|
|
124
|
+
* calls this helper after `onProjectOpened`, so a switched-to project warms
|
|
125
|
+
* its own current entries even though it keeps the boot project's dependency
|
|
126
|
+
* discovery configuration.
|
|
127
|
+
*
|
|
128
|
+
* Never throws: an absent/unparseable manifest (no project open yet, a
|
|
129
|
+
* pre-Phase-B project, a broken `vgai.project.json`) degrades to `[]` — the
|
|
130
|
+
* SAFEST fallback, not a guess. Per Vite's own `optimizeDeps.entries`
|
|
131
|
+
* resolution (`computeEntries` in vite's dep-scanner), a truthy-but-empty
|
|
132
|
+
* array short-circuits the `**\/*.html` crawl fallback WITHOUT crawling
|
|
133
|
+
* anything itself, so an unreadable manifest degrades to "no auto-discovery
|
|
134
|
+
* beyond the static `include` list" — the same conservative posture
|
|
135
|
+
* `noDiscovery: true` had, rather than falling back to a full crawl that
|
|
136
|
+
* could reach server code we know nothing about.
|
|
137
|
+
*/
|
|
138
|
+
export function computeProjectWorldEntries(projectRoot: string): string[] {
|
|
139
|
+
let manifest: ReturnType<typeof loadGameManifestDir>;
|
|
140
|
+
try {
|
|
141
|
+
manifest = loadGameManifestDir(projectRoot);
|
|
142
|
+
} catch {
|
|
143
|
+
return [];
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const entries = new Set<string>();
|
|
147
|
+
const add = (relative: string | undefined): void => {
|
|
148
|
+
if (!relative) return;
|
|
149
|
+
if (!existsSync(join(projectRoot, relative))) return;
|
|
150
|
+
entries.add(relative);
|
|
151
|
+
};
|
|
152
|
+
for (const world of manifest.roots) {
|
|
153
|
+
add(world.entry);
|
|
154
|
+
// THE ROOT'S OWN WORLD COMPONENT, when it declares one
|
|
155
|
+
// (`world.entry`). It is a SECOND discovery root for the
|
|
156
|
+
// same reason `browserToolEntries` below is: the editor's design session
|
|
157
|
+
// (`authoring/r3f-design-session.ts`) dynamic-imports that file directly,
|
|
158
|
+
// and nothing reachable from `entry` leads to it — an ingest `entry` is a
|
|
159
|
+
// host shim whose reference to the game is deliberately a VARIABLE
|
|
160
|
+
// specifier under `@vite-ignore` (so the vendored source is never
|
|
161
|
+
// typechecked against this checkout's React/fiber/three), which esbuild's
|
|
162
|
+
// scanner cannot follow by construction.
|
|
163
|
+
//
|
|
164
|
+
// Measured cold on racing-game: without this, `@react-three/cannon` is
|
|
165
|
+
// never prebundled, the design mount's `import()` fails with "Failed to
|
|
166
|
+
// fetch dynamically imported module", and the Scene view is a Boundary —
|
|
167
|
+
// i.e. the entire design-time lane is dark on a cold dep cache.
|
|
168
|
+
add(world.world?.entry);
|
|
169
|
+
}
|
|
170
|
+
return [...entries];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Dependency discovery includes every browser-loaded project module that is
|
|
175
|
+
* not reachable from a world entry: the adapter, tool contributions and portable stories.
|
|
176
|
+
*
|
|
177
|
+
* Stories are load-time entry points in their own right. A Pixi prefab may be
|
|
178
|
+
* the project's only import of `@pixi/react`; leaving its CSF module out of
|
|
179
|
+
* the initial scan lets Vite discover that renderer after the editor has
|
|
180
|
+
* already loaded React, invalidating the optimized graph and producing an
|
|
181
|
+
* invalid-hook-call split across optimizer generations.
|
|
182
|
+
*/
|
|
183
|
+
export function computeProjectOptimizeDepsEntries(projectRoot: string): string[] {
|
|
184
|
+
const entries = new Set(computeProjectWorldEntries(projectRoot));
|
|
185
|
+
// Modeling projects can have no runtime roots. Their adapter still imports
|
|
186
|
+
// browser-facing layouts and looks; discover those before the first page load.
|
|
187
|
+
if (existsSync(join(projectRoot, ADAPTER_MODULE_FILENAME)))
|
|
188
|
+
entries.add(ADAPTER_MODULE_FILENAME);
|
|
189
|
+
for (const tool of browserToolEntries(projectRoot)) entries.add(tool);
|
|
190
|
+
for (const story of browserStoryEntries(projectRoot)) entries.add(story);
|
|
191
|
+
return [...entries];
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function browserStoryEntries(projectRoot: string): string[] {
|
|
195
|
+
let manifest: ReturnType<typeof loadGameManifestDir>;
|
|
196
|
+
try {
|
|
197
|
+
manifest = loadGameManifestDir(projectRoot);
|
|
198
|
+
} catch {
|
|
199
|
+
return [];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const found: string[] = [];
|
|
203
|
+
const walk = (directory: string): void => {
|
|
204
|
+
let entries: Dirent[];
|
|
205
|
+
try {
|
|
206
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
207
|
+
} catch {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
for (const entry of entries) {
|
|
211
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
212
|
+
const absolute = join(directory, entry.name);
|
|
213
|
+
if (entry.isDirectory()) {
|
|
214
|
+
walk(absolute);
|
|
215
|
+
} else if (
|
|
216
|
+
entry.isFile() &&
|
|
217
|
+
(entry.name.endsWith('.stories.tsx') || entry.name.endsWith('.stories.ts'))
|
|
218
|
+
) {
|
|
219
|
+
found.push(relative(projectRoot, absolute).split('\\').join('/'));
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
for (const directory of projectStorySourceDirs(projectRoot, manifest)) walk(directory);
|
|
225
|
+
for (const preview of ['.storybook/preview.tsx', '.storybook/preview.ts']) {
|
|
226
|
+
if (existsSync(join(projectRoot, preview))) found.push(preview);
|
|
227
|
+
}
|
|
228
|
+
return found.sort();
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* The project's BROWSER-LOADED tool contribution modules — the second
|
|
233
|
+
* discovery root the world-entry crawl cannot reach.
|
|
234
|
+
*
|
|
235
|
+
* The editor dynamic-imports a project's tool CONTRIBUTIONS (`src/contributions/
|
|
236
|
+
* *.utility.tsx` cockpit cells, `*.document.tsx`, `*.inspector.tsx`, …) into
|
|
237
|
+
* the browser, and those pull ordinary siblings (`src/tools/
|
|
238
|
+
* dev-cockpit.utility.tsx` → `./tuning` → `@vgai/sdk/tools`). None of that
|
|
239
|
+
* hangs off any `roots[].entry`, so scoping the crawl to world entries alone
|
|
240
|
+
* left `@vgai/sdk/tools` undiscovered until the first cockpit mount —
|
|
241
|
+
* measured 2026-08-09 on a live session: "✨ new dependencies optimized:
|
|
242
|
+
* @vgai/sdk/tools" → "optimized dependencies changed. reloading", a full
|
|
243
|
+
* editor reload minutes into authoring, which dropped the in-flight play
|
|
244
|
+
* command (the exact class the C3 entries-scoping exists to prevent).
|
|
245
|
+
*
|
|
246
|
+
* The membership test is `isToolContributionModule` — the SAME predicate
|
|
247
|
+
* `project-tools.ts`'s scan feeds `tool-loader.ts`'s browser dynamic-import
|
|
248
|
+
* list, so "what the browser loads" stays one fact rather than a filename
|
|
249
|
+
* rule kept in lockstep by hand. A negation (everything except `*.tool.ts`)
|
|
250
|
+
* was measured wrong in the opposite direction: it swept each example's
|
|
251
|
+
* `src/contributions/module-source.ts` — a NODE module importing `node:fs`, and
|
|
252
|
+
* reachable only from a server-executed tool definition — into the browser
|
|
253
|
+
* crawl, which is exactly the server-only import chain this file's scoping
|
|
254
|
+
* exists to keep out. Walked recursively for the same reason
|
|
255
|
+
* the loader's own scan is: a project may organise its contributions into
|
|
256
|
+
* subdirectories.
|
|
257
|
+
*/
|
|
258
|
+
function browserToolEntries(projectRoot: string): string[] {
|
|
259
|
+
const found: string[] = [];
|
|
260
|
+
let laneDir = '';
|
|
261
|
+
const walk = (directory: string, relative: string): void => {
|
|
262
|
+
let entries: Dirent[];
|
|
263
|
+
try {
|
|
264
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
265
|
+
} catch {
|
|
266
|
+
return;
|
|
267
|
+
}
|
|
268
|
+
for (const entry of entries) {
|
|
269
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
270
|
+
const childRelative = relative === '' ? entry.name : `${relative}/${entry.name}`;
|
|
271
|
+
if (entry.isDirectory()) {
|
|
272
|
+
walk(join(directory, entry.name), childRelative);
|
|
273
|
+
} else if (entry.isFile() && isToolContributionModule(entry.name)) {
|
|
274
|
+
found.push(`${laneDir}/${childRelative}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
for (const dir of EDITOR_LANE_DIRS) {
|
|
279
|
+
laneDir = dir;
|
|
280
|
+
walk(join(projectRoot, ...dir.split('/')), '');
|
|
281
|
+
}
|
|
282
|
+
return found;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* The list handed to `optimizeDeps.entries`, spelled so Vite takes the LITERAL
|
|
287
|
+
* fast path through it.
|
|
288
|
+
*
|
|
289
|
+
* ## The silent degrade this closes
|
|
290
|
+
*
|
|
291
|
+
* Vite's `globEntries` (dep-scanner) reads the whole list as ONE decision:
|
|
292
|
+
*
|
|
293
|
+
* ```js
|
|
294
|
+
* if (resolvedPatterns.every((str) => !isDynamicPattern(str))) {
|
|
295
|
+
* return resolvedPatterns.map((p) => normalizePath(path.resolve(root, p)));
|
|
296
|
+
* }
|
|
297
|
+
* return glob(pattern, { cwd: root, ignore: ['**\/node_modules/**', …] });
|
|
298
|
+
* ```
|
|
299
|
+
*
|
|
300
|
+
* Every entry this module produces is a real file path, never a pattern — but
|
|
301
|
+
* a path is a pattern's syntax too. One entry containing `(`, `[` or a leading
|
|
302
|
+
* `!` makes `isDynamicPattern` true and routes ALL of them through `glob()`,
|
|
303
|
+
* whose unconditional `**\/node_modules/**` ignore then drops the engine-source
|
|
304
|
+
* crawl entries (`computeRuntimeSourceCrawlEntries` — they live in the project's
|
|
305
|
+
* own `node_modules/@vgai/<runtime package>/src`). Nothing reports it: the boot succeeds,
|
|
306
|
+
* `exclude` still holds, and cold-start discovery just quietly stops reaching
|
|
307
|
+
* the engine's graph — one optimizer wave and tab reload at a time, the exact
|
|
308
|
+
* class those entries exist to prevent. Measured with the real predicate
|
|
309
|
+
* (tinyglobby 0.2.x, the package Vite scans with): a project at
|
|
310
|
+
* `~/my (game)` or `~/my [wip]` makes every absolute entry dynamic; `{x}`,
|
|
311
|
+
* `+` and spaces do not.
|
|
312
|
+
*
|
|
313
|
+
* ## Why relative, and NOT escaped
|
|
314
|
+
*
|
|
315
|
+
* Escaping the specials (`escapePath`) is the obvious fix and is WRONG here,
|
|
316
|
+
* measurably: an escaped path is no longer a dynamic pattern, so Vite takes the
|
|
317
|
+
* fast path and `path.resolve`s the escaped STRING — a path with literal
|
|
318
|
+
* backslashes in it, which exists nowhere. That turns a dropped engine entry
|
|
319
|
+
* into a dropped everything.
|
|
320
|
+
*
|
|
321
|
+
* The specials come from the ROOT segment of the path, not from the parts this
|
|
322
|
+
* module builds, so spelling every under-root entry root-RELATIVE removes them
|
|
323
|
+
* from the string Vite tests: `resolve(root, 'node_modules/@vgai/project/src/
|
|
324
|
+
* loader.ts')` is the same file with no pattern syntax in the entry at all.
|
|
325
|
+
* Entries outside the Vite root (the dev server's project entries) keep their
|
|
326
|
+
* absolute spelling — Vite accepts absolute non-glob entries — because a
|
|
327
|
+
* `../../my (game)/…` relative path would carry the same specials.
|
|
328
|
+
*
|
|
329
|
+
* An entry that is STILL dynamic after that (a project whose own `src` folder
|
|
330
|
+
* is named `assets (new)`) has no correct spelling left, so it warns by name
|
|
331
|
+
* rather than degrading silently.
|
|
332
|
+
*/
|
|
333
|
+
export function viteOptimizeDepsEntries(viteRoot: string, files: readonly string[]): string[] {
|
|
334
|
+
const rootPrefix = viteRoot.endsWith(sep) ? viteRoot : `${viteRoot}${sep}`;
|
|
335
|
+
const entries = files.map((file) =>
|
|
336
|
+
isAbsolute(file) && file.startsWith(rootPrefix)
|
|
337
|
+
? relative(viteRoot, file).split(sep).join('/')
|
|
338
|
+
: file,
|
|
339
|
+
);
|
|
340
|
+
|
|
341
|
+
const dynamic = entries.filter((entry) => isDynamicPattern(entry));
|
|
342
|
+
if (dynamic.length > 0) {
|
|
343
|
+
console.warn(
|
|
344
|
+
`\n \x1b[33mWarning:\x1b[0m ${dynamic.length} dependency-scan ` +
|
|
345
|
+
`entr${dynamic.length === 1 ? 'y reads' : 'ies read'} as a glob pattern ` +
|
|
346
|
+
`(${dynamic.join(', ')}). Vite scans the whole list with glob() when any entry ` +
|
|
347
|
+
'does, and that path ignores **/node_modules/**, so the engine-source crawl entries ' +
|
|
348
|
+
'are dropped and their dependencies are discovered mid-session (an optimizer wave and ' +
|
|
349
|
+
'a tab reload each) instead of at boot. Renaming the path segment containing ' +
|
|
350
|
+
'( ) [ ] or a leading ! restores the fast path.\n',
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
return entries;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Dependency-scan entries for the checkout-backed editor dev server.
|
|
358
|
+
*
|
|
359
|
+
* That Vite instance is rooted at the engine checkout, so it must keep the
|
|
360
|
+
* editor's own HTML entry while also scanning the opened project's
|
|
361
|
+
* manifest-declared roots. A project opened from OUTSIDE the checkout stays
|
|
362
|
+
* absolute (Vite accepts absolute non-glob entries and preserves them);
|
|
363
|
+
* anything under the root is spelled root-relative — see
|
|
364
|
+
* {@link viteOptimizeDepsEntries} for why that spelling is load-bearing.
|
|
365
|
+
*/
|
|
366
|
+
export function computeDevOptimizeDepsEntries(
|
|
367
|
+
engineRoot: string,
|
|
368
|
+
projectRoot: string | undefined,
|
|
369
|
+
productEntry: string | null,
|
|
370
|
+
productContributions: readonly string[] = [],
|
|
371
|
+
): string[] {
|
|
372
|
+
// THE EDITOR'S OWN ENTRY is the PRODUCT's entry: the module the Code-OSS
|
|
373
|
+
// contribution imports, and the root of every editor import there is. It used
|
|
374
|
+
// to be `index.html`, which crawled to the same graph through a page that no
|
|
375
|
+
// longer exists. `null` when this session serves no product — then the crawl
|
|
376
|
+
// is the project's alone, which is the honest answer for a session with no
|
|
377
|
+
// editor to boot.
|
|
378
|
+
//
|
|
379
|
+
// ...AND ITS COMPOSED PACKAGES' CONTRIBUTIONS, HANDED OVER, because the crawl
|
|
380
|
+
// cannot walk to them: the product names each package as a SYNTHESIZED module
|
|
381
|
+
// (`vgai:contributions/<name>`), which hangs off no file, so the esbuild
|
|
382
|
+
// scanner never sees the `import()` rows inside it. That is the same blindness
|
|
383
|
+
// `vite-plugin-module-doorways.ts`'s header records for the other synthesized
|
|
384
|
+
// module, cured the same way — from the same declaration the browser is
|
|
385
|
+
// served (`server/session-product.ts`'s `productContributionFiles`). Measured
|
|
386
|
+
// without it, 2026-09-21: a `--template game` boot discovered storybook's
|
|
387
|
+
// preview API, three `@gltf-transform` packages and `axe-core` mid-session and
|
|
388
|
+
// Vite hard-reloaded the one tab out from under the session.
|
|
389
|
+
const entries = productEntry === null ? [] : [productEntry, ...productContributions];
|
|
390
|
+
if (projectRoot) {
|
|
391
|
+
for (const entry of computeProjectOptimizeDepsEntries(projectRoot)) {
|
|
392
|
+
entries.push(join(projectRoot, entry));
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return viteOptimizeDepsEntries(engineRoot, entries);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ---------------------------------------------------------------------------
|
|
399
|
+
// The EDITOR's own browser-side modules (C3 follow-on, 2026-08-19)
|
|
400
|
+
// ---------------------------------------------------------------------------
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* The bare (package) specifiers written in a literal module body.
|
|
404
|
+
*
|
|
405
|
+
* Deliberately lexical: the bodies these are read from are hand-written
|
|
406
|
+
* constant strings of static `import`/`export … from` lines, so a lexical
|
|
407
|
+
* read is exact for them, and it cannot execute or resolve anything.
|
|
408
|
+
*/
|
|
409
|
+
function bareSpecifiersOf(moduleSource: string): string[] {
|
|
410
|
+
const found = new Set<string>();
|
|
411
|
+
const pattern =
|
|
412
|
+
/(?:^|\s)(?:import|export)[^'"\n]*?from\s*['"]([^'"]+)['"]|import\s*['"]([^'"]+)['"]/g;
|
|
413
|
+
for (const match of moduleSource.matchAll(pattern)) {
|
|
414
|
+
const specifier = match[1] ?? match[2];
|
|
415
|
+
if (!specifier) continue;
|
|
416
|
+
if (specifier.startsWith('.') || specifier.startsWith('/') || specifier.startsWith('node:')) {
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
found.add(specifier);
|
|
420
|
+
}
|
|
421
|
+
return [...found];
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Every package specifier the editor's OWN synthesized browser modules import.
|
|
426
|
+
*
|
|
427
|
+
* ## The gap this closes
|
|
428
|
+
*
|
|
429
|
+
* `packaged.ts` serves five MODULE DOORWAYS that exist only in memory —
|
|
430
|
+
* `/__vgai-react-world-runtime`, `/__vgai-r3f-runtime`,
|
|
431
|
+
* `/__vgai-canvas-runtime`, `/__vgai-three-ingest-runtime`,
|
|
432
|
+
* `/__vgai-story-runtime`
|
|
433
|
+
* (see `vite-plugin-module-doorways.ts` for why the editor must reach react /
|
|
434
|
+
* fiber / `@pixi/react` / `@storybook/react` through the PROJECT's Vite graph
|
|
435
|
+
* rather than its own prebuilt SPA copy). Being synthesized, they hang off NO file on disk, so no
|
|
436
|
+
* `optimizeDeps.entries` value can ever crawl them: the boot scan starts at the
|
|
437
|
+
* project's world entries, tool contributions and stories, none of which import
|
|
438
|
+
* a `/__vgai-*` URL. The editor requests them at the FIRST Play mount / story
|
|
439
|
+
* preview instead — mid-session — and Vite answers a newly-seen bare specifier
|
|
440
|
+
* by re-running the optimizer and hard-reloading the controlling tab
|
|
441
|
+
* ("optimized dependencies changed. reloading"), which drops the in-flight
|
|
442
|
+
* command and, when the reload lands between two module generations, splits the
|
|
443
|
+
* React identity (`Invalid hook call`, `Cannot read properties of null (reading
|
|
444
|
+
* 'useContext')`).
|
|
445
|
+
*
|
|
446
|
+
* Measured on a real canonical-Pixi project (`packaged.ts` against a game whose
|
|
447
|
+
* only renderer is Pixi), cold `node_modules/.vite`: the boot pass prebundled
|
|
448
|
+
* 19 deps; a single request for the three synthetic modules took it to 21,
|
|
449
|
+
* adding `three` and `@react-three/fiber` — two optimizer waves, two reloads.
|
|
450
|
+
* The project had grown a workaround file importing `@pixi/react`,
|
|
451
|
+
* `@react-three/fiber` and `three` from a world entry purely to keep the crawl
|
|
452
|
+
* complete; closing the gap here is what makes that unnecessary.
|
|
453
|
+
*
|
|
454
|
+
* Read from each doorway's own module BODY — the same string the browser is
|
|
455
|
+
* served — so this list cannot drift from what the modules actually import.
|
|
456
|
+
*/
|
|
457
|
+
export const EDITOR_RUNTIME_MODULE_SPECIFIERS: readonly string[] = [
|
|
458
|
+
...new Set(
|
|
459
|
+
PACKAGED_MODULE_DOORWAYS.flatMap((doorway) => bareSpecifiersOf(doorwayModuleSource(doorway))),
|
|
460
|
+
),
|
|
461
|
+
].sort();
|
|
462
|
+
|
|
463
|
+
/**
|
|
464
|
+
* The vgai RUNTIME packages a project installs — the contract and the two
|
|
465
|
+
* shipped twins. All three are source-served whole (never prebundled), for the
|
|
466
|
+
* one-singleton reason the crawl-entry doc below states.
|
|
467
|
+
*/
|
|
468
|
+
export const RUNTIME_PACKAGE_NAMES = ['@volter/editor-project', '@volter/editor-threejs'] as const;
|
|
469
|
+
|
|
470
|
+
/** name -> that package's installed `src` directory, for the ones that resolve. */
|
|
471
|
+
export type RuntimePackageSources = ReadonlyMap<string, string>;
|
|
472
|
+
|
|
473
|
+
/** The runtime package a specifier names, or undefined. */
|
|
474
|
+
function runtimePackageOf(specifier: string): string | undefined {
|
|
475
|
+
return RUNTIME_PACKAGE_NAMES.find(
|
|
476
|
+
(name) => specifier === name || specifier.startsWith(`${name}/`),
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function isRuntimePackageSpecifier(specifier: string): boolean {
|
|
481
|
+
return runtimePackageOf(specifier) !== undefined;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
/** The package name a specifier belongs to (`three/addons/x.js` -> `three`). */
|
|
485
|
+
function packageNameOf(specifier: string): string {
|
|
486
|
+
const segments = specifier.split('/');
|
|
487
|
+
return specifier.startsWith('@') ? segments.slice(0, 2).join('/') : (segments[0] ?? specifier);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Whether `specifier` resolves from `fromDir` — Node's own resolution, rooted
|
|
492
|
+
* where the import is actually written, so a nested install is found the same
|
|
493
|
+
* way Vite would find it.
|
|
494
|
+
*
|
|
495
|
+
* The `require.resolve` fallback matters: a package published with an
|
|
496
|
+
* `exports` map that has no `require` condition throws `ERR_PACKAGE_PATH_NOT_
|
|
497
|
+
* EXPORTED` even though it is installed and perfectly resolvable by Vite. A
|
|
498
|
+
* false "not installed" there would push an INSTALLED package into
|
|
499
|
+
* `optimizeDeps.exclude` below and un-prebundle it, so fall back to the
|
|
500
|
+
* question actually being asked — is the package directory on disk? — by
|
|
501
|
+
* resolving its `package.json`, which every package exposes.
|
|
502
|
+
*/
|
|
503
|
+
export function specifierResolvesFrom(fromDir: string, specifier: string): boolean {
|
|
504
|
+
const require = createRequire(join(fromDir, '__vgai-resolve__.js'));
|
|
505
|
+
try {
|
|
506
|
+
require.resolve(specifier);
|
|
507
|
+
return true;
|
|
508
|
+
} catch {
|
|
509
|
+
// fall through to the package-directory question
|
|
510
|
+
}
|
|
511
|
+
try {
|
|
512
|
+
require.resolve(`${packageNameOf(specifier)}/package.json`);
|
|
513
|
+
return true;
|
|
514
|
+
} catch {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* The synthesized-module specifiers to add to `optimizeDeps.include` for the
|
|
521
|
+
* project rooted at `projectRoot`.
|
|
522
|
+
*
|
|
523
|
+
* Conditional on the package actually being installed for the same reason the
|
|
524
|
+
* existing `@storybook/react` entry in `packaged.ts` is: Vite ERRORS on
|
|
525
|
+
* `include`-ing a dependency it cannot resolve, and this server opens arbitrary
|
|
526
|
+
* projects — a canonical Pixi game must not be required to install the 3D
|
|
527
|
+
* renderer stack just to boot its editor. A project WITHOUT `three` simply
|
|
528
|
+
* never mounts an R3F root, so the specifier it lacks is one it never requests.
|
|
529
|
+
*
|
|
530
|
+
* Engine specifiers are excluded here on purpose: `packaged.ts` puts
|
|
531
|
+
* every runtime package in `optimizeDeps.exclude` so every one of their subpaths stays
|
|
532
|
+
* source-served (one WorldProvider identity), and an `include`
|
|
533
|
+
* entry for an excluded package is a contradiction Vite warns about. They are
|
|
534
|
+
* handled by `computeRuntimeSourceCrawlEntries` instead — as crawl ENTRIES,
|
|
535
|
+
* which reach the engine's own source graph without prebundling it.
|
|
536
|
+
*/
|
|
537
|
+
|
|
538
|
+
export function computeEditorRuntimeIncludes(projectRoot: string): string[] {
|
|
539
|
+
return EDITOR_RUNTIME_MODULE_SPECIFIERS.filter(
|
|
540
|
+
(specifier) =>
|
|
541
|
+
!isRuntimePackageSpecifier(specifier) && specifierResolvesFrom(projectRoot, specifier),
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.js', '.jsx', '.mjs'] as const;
|
|
546
|
+
|
|
547
|
+
/** The file an aliased `<runtime package>/<subpath>` import lands on, or null. */
|
|
548
|
+
function packageSubpathFile(srcDir: string, subpath: string): string | null {
|
|
549
|
+
const base = join(srcDir, subpath);
|
|
550
|
+
const candidates = [
|
|
551
|
+
base,
|
|
552
|
+
...SOURCE_EXTENSIONS.map((extension) => `${base}${extension}`),
|
|
553
|
+
...SOURCE_EXTENSIONS.map((extension) => join(base, `index${extension}`)),
|
|
554
|
+
];
|
|
555
|
+
for (const candidate of candidates) {
|
|
556
|
+
try {
|
|
557
|
+
if (statSync(candidate).isFile()) return candidate;
|
|
558
|
+
} catch {
|
|
559
|
+
// next candidate
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return null;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Engine subpaths the browser loads LAZILY — a scaffolded project's own client
|
|
567
|
+
* modules (`@vgai/game-runtime/runtime/mount-game`, `react/use-data`, the loader,
|
|
568
|
+
* the input/scene/asset readers), reached only after the editor shell is up
|
|
569
|
+
* and therefore outside the world-entry/tool/story crawl.
|
|
570
|
+
*
|
|
571
|
+
* They are crawl ENTRIES, never `optimizeDeps.include` entries, and the
|
|
572
|
+
* difference is a correctness one, not a tuning one. `include` PREBUNDLES the
|
|
573
|
+
* named module: esbuild bundles that engine file and everything it reaches by
|
|
574
|
+
* relative import into one dep chunk, so the chunk carries its own copy of
|
|
575
|
+
* `react/world-state`'s `GameContext` while the canonical
|
|
576
|
+
* `@vgai/game-runtime/react/world-state` import is served as source — two providers,
|
|
577
|
+
* one of which silently answers `null` to `useDebugProvider`/`useWorldState`.
|
|
578
|
+
* (`exclude: ['@vgai/game-runtime']` does not stop it: the scanner tests the
|
|
579
|
+
* RAW specifier, and this list used to be written in an alias spelling that
|
|
580
|
+
* check never sees. Measured on a live packaged session:
|
|
581
|
+
* eight prebundled engine modules in `.vite/deps/_metadata.json`, none of them
|
|
582
|
+
* `react/world-state`.)
|
|
583
|
+
*
|
|
584
|
+
* As entries they buy exactly what the include list was for — the third-party
|
|
585
|
+
* packages these modules import (three, zod, `three/addons/*`, fiber) are
|
|
586
|
+
* discovered in the BOOT pass instead of one mid-session optimizer wave and
|
|
587
|
+
* tab reload at a time — while the engine itself stays source-served.
|
|
588
|
+
*/
|
|
589
|
+
const LAZY_RUNTIME_CRAWL_SPECIFIERS: readonly string[] = ['@volter/editor-threejs/asset-parse-error', '@volter/editor-threejs/loader'];
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Crawl entries for the engine source the browser reaches: the document-side
|
|
593
|
+
* modules the editor's synthesized runtime modules import, plus the lazily
|
|
594
|
+
* loaded subpaths above.
|
|
595
|
+
*
|
|
596
|
+
* `packaged.ts` `exclude`s each runtime package, and Vite's dep SCANNER checks
|
|
597
|
+
* `exclude` against the raw specifier BEFORE it resolves anything — so an
|
|
598
|
+
* `import … from '@vgai/game-runtime/world3d-react'` is externalized on sight and the
|
|
599
|
+
* engine's own source graph is never crawled at all. That graph is then served
|
|
600
|
+
* as source and its bare imports are discovered one browser request at a time,
|
|
601
|
+
* each a fresh optimizer wave. Naming the engine FILES as entries walks that
|
|
602
|
+
* graph at boot instead: entries are absolute paths, so the scanner's
|
|
603
|
+
* bare-specifier `exclude` check never sees them, while the modules they reach
|
|
604
|
+
* are the very ones the browser will ask for.
|
|
605
|
+
*
|
|
606
|
+
* Measured on the same cold Pixi project as above, scoped to
|
|
607
|
+
* `react/world-state` + `world3d-react`: four `three/addons/*` entry points
|
|
608
|
+
* (`DRACOLoader`, `GLTFLoader`, `KTX2Loader`, `meshopt_decoder`) that the
|
|
609
|
+
* include list alone never reaches are discovered at boot — four waves that
|
|
610
|
+
* would otherwise fire the first time the asset lane loads a glTF.
|
|
611
|
+
*
|
|
612
|
+
* Paths are built the way `packaged.ts`'s own alias resolves them
|
|
613
|
+
* (`@vgai/game-runtime/x` -> `<that package's src>/x`), not through its
|
|
614
|
+
* `exports` map, because that alias is what Vite actually applies. A subpath
|
|
615
|
+
* that does not exist in the installed engine contributes nothing.
|
|
616
|
+
*/
|
|
617
|
+
export function computeRuntimeSourceCrawlEntries(sources: RuntimePackageSources): string[] {
|
|
618
|
+
const specifiers = new Set<string>();
|
|
619
|
+
for (const specifier of EDITOR_RUNTIME_MODULE_SPECIFIERS)
|
|
620
|
+
if (isRuntimePackageSpecifier(specifier)) specifiers.add(specifier);
|
|
621
|
+
for (const specifier of LAZY_RUNTIME_CRAWL_SPECIFIERS) specifiers.add(specifier);
|
|
622
|
+
|
|
623
|
+
const entries: string[] = [];
|
|
624
|
+
for (const specifier of specifiers) {
|
|
625
|
+
const name = runtimePackageOf(specifier);
|
|
626
|
+
const srcDir = name === undefined ? undefined : sources.get(name);
|
|
627
|
+
if (name === undefined || srcDir === undefined) continue;
|
|
628
|
+
const subpath = specifier.slice(name.length + 1);
|
|
629
|
+
if (!subpath) continue;
|
|
630
|
+
const file = packageSubpathFile(srcDir, subpath);
|
|
631
|
+
if (file) entries.push(file);
|
|
632
|
+
}
|
|
633
|
+
return entries;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/**
|
|
637
|
+
* The packages imported ANYWHERE in the installed engine's source that the
|
|
638
|
+
* OPENED PROJECT cannot resolve — to be added to `optimizeDeps.exclude`.
|
|
639
|
+
*
|
|
640
|
+
* This is the safety net that makes `computeRuntimeSourceCrawlEntries` safe to
|
|
641
|
+
* hand to Vite. Crawling engine source can reach a package the engine does not
|
|
642
|
+
* DECLARE and a given project therefore does not have: measured on this repo's
|
|
643
|
+
* engine, `src/world3d-react/r3f-adapter.tsx` imports `@react-three/fiber`
|
|
644
|
+
* and `src/world3d-react/rapier-physics-bridge.tsx` imports
|
|
645
|
+
* `@react-three/rapier` — neither of them in the engine's `dependencies`. An unresolvable bare import during the scan is not a
|
|
646
|
+
* warning: Vite collects it and `discoverProjectDependencies` THROWS "The
|
|
647
|
+
* following dependencies are imported but could not be resolved", which in
|
|
648
|
+
* `packaged.ts` rejects the boot-time `optimizeDeps()` barrier and kills the
|
|
649
|
+
* only authoring surface the user has. Vite's scanner tests `exclude` against
|
|
650
|
+
* the raw specifier before resolving, so an excluded name is externalized and
|
|
651
|
+
* never recorded as missing — the same mechanism, and the same benign degrade
|
|
652
|
+
* (that ONE feature fails in the browser; the editor boots and serves), as
|
|
653
|
+
* `SERVER_ONLY_PREBUNDLE_EXCLUDE` above.
|
|
654
|
+
*
|
|
655
|
+
* Scanning the whole `src` tree rather than only the reachable subgraph is
|
|
656
|
+
* deliberate: it is a strict superset, it costs one lexical pass over ~180
|
|
657
|
+
* files, and it stays correct when the engine grows a new optional peer without
|
|
658
|
+
* anyone remembering this file. Excluding a name nothing imports is a no-op, so
|
|
659
|
+
* the lexical scan's occasional false positive (a package-name-shaped word in a
|
|
660
|
+
* string literal) is harmless by construction — which is why a parser is not
|
|
661
|
+
* worth its cost here.
|
|
662
|
+
*
|
|
663
|
+
* ## Resolve from the PROJECT ROOT, not from the engine's own directory
|
|
664
|
+
*
|
|
665
|
+
* The first version of this asked Node whether the name resolved from
|
|
666
|
+
* the package's own src dir, which reads like the more accurate question — that is where
|
|
667
|
+
* the import is written. It is wrong, and the failure is silent until boot:
|
|
668
|
+
* every name in `packaged.ts`'s `resolve.dedupe` (`three`,
|
|
669
|
+
* `@react-three/fiber`, `pixi.js`, react, the runtime packages themselves) is resolved by
|
|
670
|
+
* Vite from `root` — the PROJECT — precisely so one copy wins. Measured on a
|
|
671
|
+
* synthetic Pixi-only project whose runtime packages link into a tree that
|
|
672
|
+
* DOES have `three`: resolving from their own src dirs judged `three` installed and
|
|
673
|
+
* left it out of this list, and the boot died on exactly the error this
|
|
674
|
+
* function exists to prevent, naming `three`, four `three/addons/*` entries and
|
|
675
|
+
* `@react-three/fiber`. Asking the project is also the conservative direction:
|
|
676
|
+
* npm hoists a dependency of the engine to the project's own `node_modules`, so
|
|
677
|
+
* "not resolvable from the project" means "not installed anywhere Vite will
|
|
678
|
+
* look", while the reverse error un-prebundles a package that works.
|
|
679
|
+
*/
|
|
680
|
+
export function computeUnresolvableRuntimeImports(
|
|
681
|
+
sources: RuntimePackageSources,
|
|
682
|
+
projectRoot: string,
|
|
683
|
+
): string[] {
|
|
684
|
+
if (sources.size === 0) return [];
|
|
685
|
+
|
|
686
|
+
const specifiers = new Set<string>();
|
|
687
|
+
const walk = (directory: string): void => {
|
|
688
|
+
let entries: Dirent[];
|
|
689
|
+
try {
|
|
690
|
+
entries = readdirSync(directory, { withFileTypes: true });
|
|
691
|
+
} catch {
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
for (const entry of entries) {
|
|
695
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') continue;
|
|
696
|
+
const absolute = join(directory, entry.name);
|
|
697
|
+
if (entry.isDirectory()) {
|
|
698
|
+
walk(absolute);
|
|
699
|
+
} else if (entry.isFile() && SOURCE_FILE_PATTERN.test(entry.name)) {
|
|
700
|
+
for (const name of importedPackageNames(absolute)) specifiers.add(name);
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
for (const srcDir of sources.values()) walk(srcDir);
|
|
705
|
+
|
|
706
|
+
return [...specifiers].filter((name) => !specifierResolvesFrom(projectRoot, name)).sort();
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* A PACKAGE's contributions, as crawl entries (WORKBENCH.md §Package or copy;
|
|
711
|
+
* ARCHITECTURE-CORE §The universal editor). On a real install a skew package
|
|
712
|
+
* (`@volter/editor-blender`, `@vgai/game`) sits under the project's `node_modules`, and
|
|
713
|
+
* the editor imports its `package.json#vgai.contributions` modules by
|
|
714
|
+
* absolute path. Vite's scanner never walks a graph that starts under
|
|
715
|
+
* `node_modules`, so every bare import those modules reach — the mesh kit's
|
|
716
|
+
* `@react-three/drei`, and through it the CommonJS `stats.js` — is served
|
|
717
|
+
* raw, one optimizer wave per request, or not at all: measured 2026-09-17 on
|
|
718
|
+
* a registry 0.5.56 install, `SyntaxError: The requested module
|
|
719
|
+
* '/node_modules/stats.js/build/stats.min.js' does not provide an export
|
|
720
|
+
* named 'default'` on every mesh contribution. Naming the contribution FILES
|
|
721
|
+
* as entries walks their graphs at boot, exactly as the engine's source
|
|
722
|
+
* entries do above.
|
|
723
|
+
*
|
|
724
|
+
* `unresolvable` is the same safety net as {@link computeUnresolvableRuntimeImports}
|
|
725
|
+
* over the package's own tree: a peer the project does not have is excluded
|
|
726
|
+
* by name rather than allowed to reject the boot-time optimizer.
|
|
727
|
+
*/
|
|
728
|
+
export interface PackageContributionCrawl {
|
|
729
|
+
readonly entries: string[];
|
|
730
|
+
readonly unresolvable: string[];
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
export function computePackageContributionCrawlEntries(
|
|
734
|
+
projectRoot: string,
|
|
735
|
+
): PackageContributionCrawl {
|
|
736
|
+
const entries: string[] = [];
|
|
737
|
+
const specifiers = new Set<string>();
|
|
738
|
+
let declared: string[] = [];
|
|
739
|
+
try {
|
|
740
|
+
const pkg = JSON.parse(readFileSync(join(projectRoot, 'package.json'), 'utf-8')) as {
|
|
741
|
+
dependencies?: Record<string, string>;
|
|
742
|
+
devDependencies?: Record<string, string>;
|
|
743
|
+
};
|
|
744
|
+
declared = [...Object.keys(pkg.dependencies ?? {}), ...Object.keys(pkg.devDependencies ?? {})];
|
|
745
|
+
} catch {
|
|
746
|
+
return { entries, unresolvable: [] };
|
|
747
|
+
}
|
|
748
|
+
const req = createRequire(join(projectRoot, 'package.json'));
|
|
749
|
+
for (const name of declared) {
|
|
750
|
+
let manifestPath: string;
|
|
751
|
+
try {
|
|
752
|
+
manifestPath = req.resolve(`${name}/package.json`);
|
|
753
|
+
} catch {
|
|
754
|
+
continue;
|
|
755
|
+
}
|
|
756
|
+
let contributions: unknown;
|
|
757
|
+
try {
|
|
758
|
+
contributions = (
|
|
759
|
+
JSON.parse(readFileSync(manifestPath, 'utf-8')) as { vgai?: { contributions?: unknown } }
|
|
760
|
+
).vgai?.contributions;
|
|
761
|
+
} catch {
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
if (!Array.isArray(contributions)) continue;
|
|
765
|
+
const dir = dirname(manifestPath);
|
|
766
|
+
for (const entry of contributions) {
|
|
767
|
+
if (typeof entry !== 'string') continue;
|
|
768
|
+
const file = join(dir, entry);
|
|
769
|
+
if (existsSync(file)) entries.push(file);
|
|
770
|
+
}
|
|
771
|
+
const walk = (directory: string): void => {
|
|
772
|
+
let found: Dirent[];
|
|
773
|
+
try {
|
|
774
|
+
found = readdirSync(directory, { withFileTypes: true });
|
|
775
|
+
} catch {
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
for (const item of found) {
|
|
779
|
+
if (item.name.startsWith('.') || item.name === 'node_modules') continue;
|
|
780
|
+
const absolute = join(directory, item.name);
|
|
781
|
+
if (item.isDirectory()) walk(absolute);
|
|
782
|
+
else if (item.isFile() && SOURCE_FILE_PATTERN.test(item.name))
|
|
783
|
+
for (const imported of importedPackageNames(absolute)) specifiers.add(imported);
|
|
784
|
+
}
|
|
785
|
+
};
|
|
786
|
+
walk(join(dir, 'contributions'));
|
|
787
|
+
walk(join(dir, 'src'));
|
|
788
|
+
}
|
|
789
|
+
const unresolvable = [...specifiers]
|
|
790
|
+
.filter((name) => !specifierResolvesFrom(projectRoot, name))
|
|
791
|
+
.sort();
|
|
792
|
+
return { entries, unresolvable };
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const SOURCE_FILE_PATTERN = /\.(?:ts|tsx|mts|js|jsx|mjs)$/;
|
|
796
|
+
const IMPORT_PATTERN = /(?:from|import|require)\s*\(?\s*['"]([^'"\n]+)['"]/g;
|
|
797
|
+
/** npm's own name grammar — anything else the lexical scan caught is prose. */
|
|
798
|
+
const PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9-~][a-z0-9-._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/;
|
|
799
|
+
|
|
800
|
+
/** The package names a source file's bare imports name; `[]` if unreadable. */
|
|
801
|
+
function importedPackageNames(file: string): string[] {
|
|
802
|
+
let source: string;
|
|
803
|
+
try {
|
|
804
|
+
source = readFileSync(file, 'utf-8');
|
|
805
|
+
} catch {
|
|
806
|
+
return [];
|
|
807
|
+
}
|
|
808
|
+
const names: string[] = [];
|
|
809
|
+
for (const match of source.matchAll(IMPORT_PATTERN)) {
|
|
810
|
+
const specifier = match[1];
|
|
811
|
+
if (!specifier || isLocalSpecifier(specifier)) continue;
|
|
812
|
+
const name = packageNameOf(specifier);
|
|
813
|
+
if (PACKAGE_NAME_PATTERN.test(name)) names.push(name);
|
|
814
|
+
}
|
|
815
|
+
return names;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
/** Resolved by path or by this repo's own aliases — never by node_modules. */
|
|
819
|
+
function isLocalSpecifier(specifier: string): boolean {
|
|
820
|
+
return (
|
|
821
|
+
specifier.startsWith('.') ||
|
|
822
|
+
specifier.startsWith('/') ||
|
|
823
|
+
specifier.startsWith('node:') ||
|
|
824
|
+
specifier.startsWith('virtual:') ||
|
|
825
|
+
isRuntimePackageSpecifier(specifier)
|
|
826
|
+
);
|
|
827
|
+
}
|