@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,184 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `vgai-creation-site-write` — the `/__ingest-source/*` dev-server
|
|
3
|
+
* routes that let an ingest edit be written into the game's OWN source at the
|
|
4
|
+
* line the creation-site index anchored it to.
|
|
5
|
+
*
|
|
6
|
+
* This file is wiring only; every decision lives in `server/creation-site-write.ts`
|
|
7
|
+
* (ownership, containment, the checksum guard) and `src/creation-site-edit.ts`
|
|
8
|
+
* (what may be rewritten). The split is the same one `vite-plugin-ui-oid.ts`
|
|
9
|
+
* makes, and for the same reason: a handler that is a pure function of
|
|
10
|
+
* `(body, projectRoot, engineRoot)` is one a unit test can drive without a
|
|
11
|
+
* server.
|
|
12
|
+
*
|
|
13
|
+
* `getProjectRoot` is a THUNK, exactly like `uiOidPlugin`'s: `server/dev.ts`
|
|
14
|
+
* keeps `process.env.VGAI_PROJECT` current as projects open and close
|
|
15
|
+
* (`onProjectOpened`), so a route resolved per request follows the switch and a
|
|
16
|
+
* snapshot taken at config time would not.
|
|
17
|
+
*
|
|
18
|
+
* ROUTES ARE ALWAYS REGISTERED, and refuse per request. There is no
|
|
19
|
+
* "only mount these when the project is writable" branch, because ownership can
|
|
20
|
+
* change under a running server (a project switch) and because a route that is
|
|
21
|
+
* absent gives a client a different failure than a route that says no — and the
|
|
22
|
+
* honest answer, with its reason, is the product surface here.
|
|
23
|
+
*/
|
|
24
|
+
import type { Plugin } from 'vite';
|
|
25
|
+
import {
|
|
26
|
+
bindIngestWriteInvalidation,
|
|
27
|
+
type HandlerResult,
|
|
28
|
+
handleIngestApply,
|
|
29
|
+
handleIngestInspect,
|
|
30
|
+
handleIngestOwnership,
|
|
31
|
+
handleIngestPrepare,
|
|
32
|
+
handleIngestRead,
|
|
33
|
+
} from './server/creation-site-write';
|
|
34
|
+
import { editorChromeStampBoundary } from './server/project-script-hmr';
|
|
35
|
+
|
|
36
|
+
interface RequestLike {
|
|
37
|
+
body?: unknown;
|
|
38
|
+
url?: string | undefined;
|
|
39
|
+
method?: string | undefined;
|
|
40
|
+
on(event: string, listener: (chunk?: unknown) => void): void;
|
|
41
|
+
}
|
|
42
|
+
interface ResponseLike {
|
|
43
|
+
statusCode: number;
|
|
44
|
+
setHeader(name: string, value: string): void;
|
|
45
|
+
end(body?: string): void;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function send(res: ResponseLike, result: HandlerResult): void {
|
|
49
|
+
res.statusCode = result.status ?? 200;
|
|
50
|
+
res.setHeader('Content-Type', 'application/json');
|
|
51
|
+
res.end(JSON.stringify(result.body));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The request body — FROM `req.body` when something upstream already parsed it,
|
|
56
|
+
* and only otherwise from the stream.
|
|
57
|
+
*
|
|
58
|
+
* That first line is not defensive coding, it is the only thing that works
|
|
59
|
+
* here. `server/dev.ts` mounts Vite in middleware mode BEHIND an express app
|
|
60
|
+
* (`app.use(editorRouter)` then `app.use(vite.middlewares)`), and the editor
|
|
61
|
+
* router installs `express.json()` for every route it sees — so by the time a
|
|
62
|
+
* Vite plugin middleware runs, the POST body has already been consumed and
|
|
63
|
+
* attached to `req.body`. Reading the stream instead waits for a `data`/`end`
|
|
64
|
+
* pair that fired minutes ago and NEVER RESOLVES: the request hangs, the client
|
|
65
|
+
* awaits forever, and — because nothing threw — not one line appears in any log.
|
|
66
|
+
* Measured live on SimCity: the write silently did nothing while every gate
|
|
67
|
+
* reported open. `vite-plugin-ui-oid.ts`'s `readJson` has the same first line
|
|
68
|
+
* for the same reason; do not "simplify" it away.
|
|
69
|
+
*/
|
|
70
|
+
export async function readBody(req: RequestLike): Promise<Record<string, unknown>> {
|
|
71
|
+
const parsed = (req as { body?: unknown }).body;
|
|
72
|
+
if (parsed && typeof parsed === 'object') return parsed as Record<string, unknown>;
|
|
73
|
+
const chunks: Buffer[] = [];
|
|
74
|
+
await new Promise<void>((resolveBody, reject) => {
|
|
75
|
+
req.on('data', (chunk) => chunks.push(Buffer.from(chunk as Uint8Array)));
|
|
76
|
+
req.on('end', () => resolveBody());
|
|
77
|
+
req.on('error', (error) => reject(error));
|
|
78
|
+
});
|
|
79
|
+
const text = Buffer.concat(chunks).toString('utf8');
|
|
80
|
+
if (!text) return {};
|
|
81
|
+
return JSON.parse(text) as Record<string, unknown>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** One handler per route, as a table — `vite-plugin-ui-oid.ts`'s `postRoutes`
|
|
85
|
+
* shape. Every entry is a pure function of `(body, projectRoot, engineRoot)`,
|
|
86
|
+
* which is what lets `creation-site-write.test.ts` drive them with no server. */
|
|
87
|
+
const POST_ROUTES: Record<
|
|
88
|
+
string,
|
|
89
|
+
(
|
|
90
|
+
body: Record<string, unknown>,
|
|
91
|
+
projectRoot: string | undefined,
|
|
92
|
+
engineRoot: string,
|
|
93
|
+
) => HandlerResult
|
|
94
|
+
> = {
|
|
95
|
+
'/__ingest-source/prepare': handleIngestPrepare,
|
|
96
|
+
'/__ingest-source/inspect': handleIngestInspect,
|
|
97
|
+
'/__ingest-source/read': handleIngestRead,
|
|
98
|
+
'/__ingest-source/apply': handleIngestApply,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/** The response for one `/__ingest-source/*` request, or `null` when the path is
|
|
102
|
+
* not ours and the request belongs to the next middleware. A THROWN handler is
|
|
103
|
+
* a bug, not a refusal, and must not read as one: refusals are 200/403 with a
|
|
104
|
+
* `reason` the UI shows, so a throw becomes an explicit 500. */
|
|
105
|
+
async function respondTo(
|
|
106
|
+
path: string,
|
|
107
|
+
req: RequestLike,
|
|
108
|
+
projectRoot: string | undefined,
|
|
109
|
+
engineRoot: string,
|
|
110
|
+
): Promise<HandlerResult | null> {
|
|
111
|
+
try {
|
|
112
|
+
if (path === '/__ingest-source/ownership') {
|
|
113
|
+
return handleIngestOwnership(projectRoot, engineRoot);
|
|
114
|
+
}
|
|
115
|
+
const handler = POST_ROUTES[path];
|
|
116
|
+
if (!handler) return null;
|
|
117
|
+
return handler(await readBody(req), projectRoot, engineRoot);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
return {
|
|
120
|
+
status: 500,
|
|
121
|
+
body: { error: error instanceof Error ? error.message : String(error) },
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* This plugin's Vite name — the ONE spelling, so a host can ask its own
|
|
128
|
+
* resolved plugin list whether it serves `/__ingest-source/*` instead of
|
|
129
|
+
* declaring the same fact a second time. `vite-plugin-ui-oid.ts`'s
|
|
130
|
+
* `UI_OID_PLUGIN_NAME` is the sibling.
|
|
131
|
+
*/
|
|
132
|
+
export const CREATION_SITE_WRITE_PLUGIN_NAME = 'vgai-creation-site-write';
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Does this Vite instance serve the `/__ingest-source/*` ownership + write
|
|
136
|
+
* routes?
|
|
137
|
+
*
|
|
138
|
+
* Read off the RESOLVED plugin list, never declared — the same rule, and the
|
|
139
|
+
* same defect behind it, as {@link servesUiSourceRoutes}: an ingest edit's
|
|
140
|
+
* recorder is a fact about THIS SESSION'S HOST, and `import.meta.env.DEV` is a
|
|
141
|
+
* fact about how the editor shell was built. This is what `/__editor/project`
|
|
142
|
+
* reports as `ingestSourceWrite` and what
|
|
143
|
+
* `src/ui-source/tier-source-write-backend.ts` hands the ingest lane.
|
|
144
|
+
*/
|
|
145
|
+
export function servesIngestSourceRoutes(plugins: readonly { name: string }[]): boolean {
|
|
146
|
+
return plugins.some((plugin) => plugin.name === CREATION_SITE_WRITE_PLUGIN_NAME);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function creationSiteWritePlugin(
|
|
150
|
+
getProjectRoot: () => string | undefined,
|
|
151
|
+
engineRoot: string,
|
|
152
|
+
): Plugin {
|
|
153
|
+
return {
|
|
154
|
+
name: CREATION_SITE_WRITE_PLUGIN_NAME,
|
|
155
|
+
configureServer(server) {
|
|
156
|
+
// `apply` writes the game's own source, so it invalidates the modules it
|
|
157
|
+
// replaced — see `creation-site-write.ts`'s
|
|
158
|
+
// `writtenSourceInvalidationGraph` for the stale-remount this closes, and
|
|
159
|
+
// why the watcher is not allowed to be the only path.
|
|
160
|
+
//
|
|
161
|
+
// The boundary: a written game module's stamp propagates through its
|
|
162
|
+
// importers so the game's own subgraph re-evaluates, but must STOP at
|
|
163
|
+
// editor chrome — an unbounded walk re-stamped `play-mode.ts` and split
|
|
164
|
+
// its container singleton. ONE shared spelling with the ui-oid write
|
|
165
|
+
// route — see `editorChromeStampBoundary`'s doc.
|
|
166
|
+
bindIngestWriteInvalidation(
|
|
167
|
+
server.moduleGraph,
|
|
168
|
+
editorChromeStampBoundary(engineRoot, getProjectRoot),
|
|
169
|
+
);
|
|
170
|
+
server.middlewares.use(async (req, res, next) => {
|
|
171
|
+
const path = (req.url ?? '').split('?')[0] ?? '';
|
|
172
|
+
if (!path.startsWith('/__ingest-source/')) return next();
|
|
173
|
+
const result = await respondTo(
|
|
174
|
+
path,
|
|
175
|
+
req as unknown as RequestLike,
|
|
176
|
+
getProjectRoot(),
|
|
177
|
+
engineRoot,
|
|
178
|
+
);
|
|
179
|
+
if (!result) return next();
|
|
180
|
+
send(res as unknown as ResponseLike, result);
|
|
181
|
+
});
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `vgai-creation-site` transform — stamps every direct
|
|
3
|
+
* `new <Ctor>(…)` in a served PROJECT module so the editor can name the source
|
|
4
|
+
* line that created a selected live object. The rewriting rules and why they
|
|
5
|
+
* are semantics-preserving live in `server/creation-site-transform.ts`; this
|
|
6
|
+
* file is the Vite wiring and the OWNERSHIP BOUNDARY.
|
|
7
|
+
*
|
|
8
|
+
* SCOPE IS THE SAME BOUNDARY THE GAME-GLOBALS PRELUDE USES, deliberately.
|
|
9
|
+
* `creationSiteScopeFor` is `shouldShadowGameGlobals`'s predicate plus the
|
|
10
|
+
* matched root, so "is this file the project's own code?" has exactly one
|
|
11
|
+
* answer in this codebase rather than two that can drift. The editor's own
|
|
12
|
+
* modules are therefore never stamped: `packages/editor/src` is only ever in
|
|
13
|
+
* the root set through `ingestGameShadowRoots`, which names the
|
|
14
|
+
* `ingest/games/**` fixture subtree and nothing else — and those fixtures ARE
|
|
15
|
+
* game code.
|
|
16
|
+
*
|
|
17
|
+
* REGISTERED IN BOTH CONFIGS, exactly like `gameGlobalsShadowPlugin`: the
|
|
18
|
+
* repo-root `vite.config.ts` covers the in-tree ingest fixtures, and
|
|
19
|
+
* `server/dev.ts` covers an opened project's root. In dev both are live and both `transform` hooks see the same
|
|
20
|
+
* modules; the marker check in `transformCreationSites` makes the overlap a
|
|
21
|
+
* no-op.
|
|
22
|
+
*
|
|
23
|
+
* `enforce: 'pre'` IS LOAD-BEARING. It puts this transform ahead of the
|
|
24
|
+
* game-globals prelude (which prepends a line, shifting every line number) and
|
|
25
|
+
* ahead of esbuild's TS transpile, so the `line:col` we bake in points at the
|
|
26
|
+
* author's own file on disk. Moving it out of `pre` silently makes every
|
|
27
|
+
* recorded line wrong by one.
|
|
28
|
+
*/
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
import type { Plugin } from 'vite';
|
|
31
|
+
import { transformCreationSites } from './server/creation-site-transform';
|
|
32
|
+
import { shouldShadowGameGlobals } from './server/game-globals-shadow';
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The project root that owns `file`, or `null` when no root does (the editor's
|
|
36
|
+
* own source, `node_modules`, a non-module asset).
|
|
37
|
+
*
|
|
38
|
+
* Returns the ROOT and not just a boolean because the recorded path must be
|
|
39
|
+
* root-relative: that string is shown in the inspector and read back through
|
|
40
|
+
* `vgai eval`, and an absolute path would put the host's directory layout into
|
|
41
|
+
* a product surface. Longest matching root wins, so a project nested inside
|
|
42
|
+
* another root is described against the nearest one.
|
|
43
|
+
*/
|
|
44
|
+
export function creationSiteScopeFor(
|
|
45
|
+
file: string,
|
|
46
|
+
roots: Iterable<string>,
|
|
47
|
+
): { root: string; displayFile: string } | null {
|
|
48
|
+
let best: string | null = null;
|
|
49
|
+
for (const root of roots) {
|
|
50
|
+
if (!shouldShadowGameGlobals(file, [root])) continue;
|
|
51
|
+
if (best === null || root.length > best.length) best = root;
|
|
52
|
+
}
|
|
53
|
+
if (best === null) return null;
|
|
54
|
+
// POSIX separators: this string is an identifier shown to a user and read by
|
|
55
|
+
// an agent, not a path anything opens.
|
|
56
|
+
return { root: best, displayFile: path.relative(best, file).split(path.sep).join('/') };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* `getRoots` is a thunk, not a snapshot — `dev.ts` mutates its root set when a
|
|
61
|
+
* project opens after boot (`onProjectOpened`), the same reason
|
|
62
|
+
* `gameGlobalsShadowPlugin` takes one.
|
|
63
|
+
*/
|
|
64
|
+
export function creationSitePlugin(getRoots: () => Iterable<string>): Plugin {
|
|
65
|
+
return {
|
|
66
|
+
name: 'vgai-creation-site',
|
|
67
|
+
enforce: 'pre',
|
|
68
|
+
transform(code: string, id: string) {
|
|
69
|
+
const file = id.split('?')[0]!;
|
|
70
|
+
const scope = creationSiteScopeFor(file, getRoots());
|
|
71
|
+
if (!scope) return null;
|
|
72
|
+
const result = transformCreationSites(code, scope.displayFile);
|
|
73
|
+
if (!result) return null;
|
|
74
|
+
// No source map: this transform only INSERTS text, and the shipped
|
|
75
|
+
// precedent (`vite-plugin-game-globals.ts`) makes the same trade. The
|
|
76
|
+
// positions that matter are the ones baked into the emitted literals.
|
|
77
|
+
return { code: result.code, map: null };
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
}
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* vite-plugin-game-static — THE dev-server route that serves a vendored game's own bytes
|
|
3
|
+
* VERBATIM (no vite transform), for every vendored game under `vendor/games/`, whatever
|
|
4
|
+
* library it uses (Wave 0.6, ONE INGEST HOME). It merges the two per-library plugins that
|
|
5
|
+
* used to live here and in `vite-plugin-react-game-static.ts`.
|
|
6
|
+
*
|
|
7
|
+
* Verbatim matters because a transform would break the very properties that let an
|
|
8
|
+
* UNMODIFIED game run: a game's bare `import 'pixi.js'` must survive to resolve to the
|
|
9
|
+
* host's own instance in the editor's realm (not be rewritten to `/node_modules/.vite/deps`),
|
|
10
|
+
* and an AssetPack `.json` spritesheet must stay raw JSON (not become an ESM module). This is pure
|
|
11
|
+
* HOST wiring — it never touches vendored game source.
|
|
12
|
+
*
|
|
13
|
+
* Two id-generic routes, one plugin, zero per-game branches. Which routes a given game
|
|
14
|
+
* uses follows from HOW it is vendored, never from what draws it:
|
|
15
|
+
*
|
|
16
|
+
* 1. `/vendor/games/<id>/<rest>` -> `vendor/games/<id>/public/<rest>`.
|
|
17
|
+
* The VENDORED-PUBLIC route: this is the shape a game's own `import.meta.url`-derived
|
|
18
|
+
* asset base produces when Vite serves its modules from the vendored tree (see the
|
|
19
|
+
* empirical finding below). Anything not under that game's `public/` falls through to
|
|
20
|
+
* Vite untouched, which is what keeps the game's real `src/` modules served normally.
|
|
21
|
+
*
|
|
22
|
+
* 2. A ROOT-relative path (`/logo-no-bg.png`, `/tiles/<rest>`, `/assets/<rest>`) resolved
|
|
23
|
+
* against each vendored game's `public/` in turn, first hit wins. Games that ship
|
|
24
|
+
* literal absolute-root asset URLs need this, and so does every Pixi/AssetPack game (its
|
|
25
|
+
* `Assets.init({ basePath: 'assets' })` is relative to the DOCUMENT, which inside the
|
|
26
|
+
* editor is the root). It is restricted to the extensions a game asks for with a plain
|
|
27
|
+
* URL, to files that genuinely exist, and — the guard that actually holds — to requests
|
|
28
|
+
* Vite itself already declined.
|
|
29
|
+
*
|
|
30
|
+
* Both routes scope themselves from the VENDORED TREE — every `vendor/games/<id>/` that
|
|
31
|
+
* actually has a `public/` directory — so a second such game is a folder, not an edit here.
|
|
32
|
+
*
|
|
33
|
+
* ## EMPIRICAL FINDING, kept because it is not obvious
|
|
34
|
+
*
|
|
35
|
+
* react-rpg's `src/config/constants.js` builds its tile-asset BASE URL from its own
|
|
36
|
+
* `import.meta.url`, slicing off everything from the literal substring `'src'` onward and
|
|
37
|
+
* appending `'tiles/'`. Upstream serves that module at `/src/config/constants.js` (Vite root
|
|
38
|
+
* = their repo root), so the slice keeps the ORIGIN and nothing else, yielding an
|
|
39
|
+
* origin-rooted `/tiles/` URL there.
|
|
40
|
+
*
|
|
41
|
+
* The vendored folder here is therefore named `src/`, matching upstream EXACTLY — NOT
|
|
42
|
+
* renamed (the pixi precedent's convention would suggest `game/`, but a renamed folder
|
|
43
|
+
* actively BREAKS this game): this dev server's URL for `constants.js` would be
|
|
44
|
+
* `http://<host>/vendor/games/react-rpg/game/config/constants.js` if renamed — which
|
|
45
|
+
* contains NO `'src'` substring anywhere, so `indexOf('src')` returns `-1`;
|
|
46
|
+
* `String.prototype.substring` clamps a negative end to `0`, so the slice degenerates to
|
|
47
|
+
* `''`, and the computed "URL" is the bare string `'tiles/'` — NOT a valid absolute URL.
|
|
48
|
+
* The game's own `features/map/map-padding.jsx` then does `new URL('./tile.png', REF_URL)`,
|
|
49
|
+
* and `new URL()`'s base argument MUST itself be a valid absolute URL or the constructor
|
|
50
|
+
* THROWS (`TypeError: Failed to construct 'URL': Invalid base URL`) — verified against the
|
|
51
|
+
* real dev server; a hard runtime crash the moment the dungeon view renders one tile.
|
|
52
|
+
* Keeping the folder named `src/` makes `indexOf('src')` find the REAL segment, so the slice
|
|
53
|
+
* yields a genuine origin-rooted prefix — `http://<host>/vendor/games/react-rpg/` +
|
|
54
|
+
* `'tiles/'` — which is route 2 above. (`vendor/games/verify-unaltered.mjs`'s and
|
|
55
|
+
* `react-rpg.UPSTREAM.md`'s records of the same finding come from the zero-diff side.)
|
|
56
|
+
*/
|
|
57
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
58
|
+
import { readFile } from 'node:fs/promises';
|
|
59
|
+
import { extname, join, normalize, resolve } from 'node:path';
|
|
60
|
+
import type { Plugin } from 'vite';
|
|
61
|
+
|
|
62
|
+
// Exported so `vite-plugin-project-game-static.ts` (D-X2, the external-folder
|
|
63
|
+
// verbatim-serving sibling of this plugin) reuses the SAME MIME table rather
|
|
64
|
+
// than drifting a second copy — both plugins serve the identical class of
|
|
65
|
+
// content (a game bundle + JSON spritesheets + image/audio/font assets), just
|
|
66
|
+
// rooted at a different directory.
|
|
67
|
+
export const MIME: Record<string, string> = {
|
|
68
|
+
'.mjs': 'text/javascript',
|
|
69
|
+
'.js': 'text/javascript',
|
|
70
|
+
'.json': 'application/json',
|
|
71
|
+
'.png': 'image/png',
|
|
72
|
+
'.webp': 'image/webp',
|
|
73
|
+
'.jpg': 'image/jpeg',
|
|
74
|
+
'.jpeg': 'image/jpeg',
|
|
75
|
+
'.gif': 'image/gif',
|
|
76
|
+
'.svg': 'image/svg+xml',
|
|
77
|
+
// Video is media in the same sense as an image: a reference clip or a
|
|
78
|
+
// generated motion study is served to a plain <video src>, and without these
|
|
79
|
+
// two entries the request fell through to the SPA fallback and the element
|
|
80
|
+
// reported an unsupported source while the bytes sat right there.
|
|
81
|
+
'.mp4': 'video/mp4',
|
|
82
|
+
'.webm': 'video/webm',
|
|
83
|
+
'.mp3': 'audio/mpeg',
|
|
84
|
+
'.ogg': 'audio/ogg',
|
|
85
|
+
'.wav': 'audio/wav',
|
|
86
|
+
'.woff2': 'font/woff2',
|
|
87
|
+
'.woff': 'font/woff',
|
|
88
|
+
'.ttf': 'font/ttf',
|
|
89
|
+
// 3D model bytes are the same class of content as an image or an audio clip —
|
|
90
|
+
// a game asks for them with a plain URL and a loader parses the bytes. The
|
|
91
|
+
// table lacked them only because the early vendored games all drew from
|
|
92
|
+
// sprites: an R3F game's `useGLTF('/models/Court.glb')` is a ROOT-relative
|
|
93
|
+
// model request, so it needs both this MIME entry and the
|
|
94
|
+
// `ROOT_RELATIVE_MEDIA` membership below.
|
|
95
|
+
'.glb': 'model/gltf-binary',
|
|
96
|
+
'.gltf': 'model/gltf+json',
|
|
97
|
+
// A radiance/HDR environment map is media in exactly the same sense, and it
|
|
98
|
+
// has no registered IANA type — `image/vnd.radiance` is the de-facto one, and
|
|
99
|
+
// what it is called matters less than that the bytes arrive unmangled, since
|
|
100
|
+
// three's `RGBELoader` parses them itself from an ArrayBuffer. Missing here,
|
|
101
|
+
// a root-relative `textures/x.hdr` fell through to the editor's SPA fallback
|
|
102
|
+
// and the loader reported `Bad File Format: bad initial token` — it was
|
|
103
|
+
// parsing index.html. Measured on the R3F racing-game ingest, whose drei
|
|
104
|
+
// `<Environment files="textures/dikhololo_night_1k.hdr" />` is the first HDR
|
|
105
|
+
// request any vendored game has made.
|
|
106
|
+
'.hdr': 'image/vnd.radiance',
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Extensions the ROOT-RELATIVE fallback is willing to claim: everything a game asks for
|
|
111
|
+
* with a plain URL and parses itself. It is `MIME` minus the script types — a vendored
|
|
112
|
+
* game's `public/` may answer for its own bytes, but it may never answer for a MODULE.
|
|
113
|
+
*
|
|
114
|
+
* ## Why `.json` is in this set, and what makes it safe
|
|
115
|
+
*
|
|
116
|
+
* It was not, and it had to be. Measured on the `bubbo-bubbo` ingest: an AssetPack game's
|
|
117
|
+
* spritesheets ARE `.json` (its `Assets.init({ basePath: 'assets' })` asks for
|
|
118
|
+
* `/assets/images/preload.webp.json`), so a media-only fallback served its atlas PNGs and
|
|
119
|
+
* dropped every atlas that names their frames — `[Loader.load] Failed to load … SyntaxError:
|
|
120
|
+
* Unexpected token '<'`, because the request fell through to the SPA fallback and Pixi was
|
|
121
|
+
* handed `index.html`.
|
|
122
|
+
*
|
|
123
|
+
* What used to make `.json` unsafe was this route's POSITION, not its extension: it ran
|
|
124
|
+
* ahead of Vite, with no id in the URL to scope it, so a vendored `public/` could shadow a
|
|
125
|
+
* root-relative request the editor itself owns. That is now closed STRUCTURALLY — the
|
|
126
|
+
* fallback is installed as a Vite POST middleware ({@link gameStaticPlugin}), so it only
|
|
127
|
+
* ever sees a request Vite's own transform and static routes already declined. The editor
|
|
128
|
+
* can no longer be shadowed because the editor already had its turn.
|
|
129
|
+
*
|
|
130
|
+
* Script types stay out anyway: at this position they are reachable only when Vite 404s
|
|
131
|
+
* them, but a vendored `public/main.js` answering an unresolved editor import would turn a
|
|
132
|
+
* loud missing-module error into a silently wrong one, and that trade is never worth it.
|
|
133
|
+
*/
|
|
134
|
+
const ROOT_RELATIVE_FALLBACK = new Set([
|
|
135
|
+
'.json',
|
|
136
|
+
'.png',
|
|
137
|
+
'.webp',
|
|
138
|
+
'.jpg',
|
|
139
|
+
'.jpeg',
|
|
140
|
+
'.gif',
|
|
141
|
+
'.svg',
|
|
142
|
+
'.mp3',
|
|
143
|
+
'.ogg',
|
|
144
|
+
'.wav',
|
|
145
|
+
'.woff2',
|
|
146
|
+
'.woff',
|
|
147
|
+
'.ttf',
|
|
148
|
+
'.glb',
|
|
149
|
+
'.gltf',
|
|
150
|
+
'.hdr',
|
|
151
|
+
]);
|
|
152
|
+
|
|
153
|
+
export const VENDOR_PREFIX = '/vendor/games/';
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Every vendored game id that ships a `public/` directory (both routes' scope). Read once at
|
|
157
|
+
* plugin construction (the vendored tree is checked-in source, not something that changes
|
|
158
|
+
* while a dev server runs) and tolerant of the directory being absent entirely.
|
|
159
|
+
*/
|
|
160
|
+
export function discoverVendoredGameIds(vendorRoot: string): string[] {
|
|
161
|
+
try {
|
|
162
|
+
return readdirSync(vendorRoot, { withFileTypes: true })
|
|
163
|
+
.filter((e) => e.isDirectory() && !e.name.startsWith('_') && !e.name.startsWith('.'))
|
|
164
|
+
.map((e) => e.name)
|
|
165
|
+
.filter((id) => {
|
|
166
|
+
try {
|
|
167
|
+
return statSync(join(vendorRoot, id, 'public')).isDirectory();
|
|
168
|
+
} catch {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
})
|
|
172
|
+
.sort();
|
|
173
|
+
} catch {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** Path-traversal guard, applied to every candidate either resolver produces: stay inside
|
|
179
|
+
* the vendored tree, whatever `..` the URL contained. */
|
|
180
|
+
function insideVendorTree(vendorRoot: string, candidates: string[]): string[] {
|
|
181
|
+
return candidates.map((c) => normalize(c)).filter((c) => c.startsWith(vendorRoot));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* THE ID-CARRYING route: `/vendor/games/<id>/<rest>` -> `vendor/games/<id>/public/<rest>`,
|
|
186
|
+
* or `[]` for "not ours, fall through". Scoped by the id in the URL itself, so it is safe
|
|
187
|
+
* ahead of Vite and is installed there.
|
|
188
|
+
*
|
|
189
|
+
* Pure (path math only, no I/O) and exported for direct unit testing — the traversal guard
|
|
190
|
+
* in particular deserves a test that needs no dev server.
|
|
191
|
+
*/
|
|
192
|
+
export function resolveVendoredPublicPath(
|
|
193
|
+
vendorRoot: string,
|
|
194
|
+
gameIds: readonly string[],
|
|
195
|
+
urlPath: string,
|
|
196
|
+
): string[] {
|
|
197
|
+
if (!urlPath.startsWith(VENDOR_PREFIX)) return [];
|
|
198
|
+
const rest = urlPath.slice(VENDOR_PREFIX.length);
|
|
199
|
+
const slash = rest.indexOf('/');
|
|
200
|
+
if (slash <= 0) return [];
|
|
201
|
+
const id = rest.slice(0, slash);
|
|
202
|
+
if (!gameIds.includes(id)) return [];
|
|
203
|
+
return insideVendorTree(vendorRoot, [join(vendorRoot, id, 'public', rest.slice(slash + 1))]);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* THE ROOT-RELATIVE fallback: a bare `/logo-no-bg.png`, `/tiles/wall.png` or
|
|
208
|
+
* `/assets/images/preload.webp.json`, resolved against each vendored game's `public/` in
|
|
209
|
+
* turn — first hit wins at the middleware, so ORDER is the contract, not a single answer.
|
|
210
|
+
*
|
|
211
|
+
* Games that ship literal absolute-root asset URLs need this, and there are two shapes of
|
|
212
|
+
* them: react-rpg derives an origin-rooted base from its own `import.meta.url`, and any
|
|
213
|
+
* Pixi/AssetPack game asks for its bundle under a relative `basePath` that the editor
|
|
214
|
+
* document resolves to the root. Neither can be given an id in the URL without editing the
|
|
215
|
+
* game, which is the one thing an ingest may never do.
|
|
216
|
+
*
|
|
217
|
+
* There is no id here to scope it, so its safety is POSITIONAL: see
|
|
218
|
+
* {@link ROOT_RELATIVE_FALLBACK} and {@link gameStaticPlugin}.
|
|
219
|
+
*/
|
|
220
|
+
export function resolveVendoredRootRelativePath(
|
|
221
|
+
vendorRoot: string,
|
|
222
|
+
gameIds: readonly string[],
|
|
223
|
+
urlPath: string,
|
|
224
|
+
): string[] {
|
|
225
|
+
if (urlPath.startsWith(VENDOR_PREFIX)) return [];
|
|
226
|
+
if (!ROOT_RELATIVE_FALLBACK.has(extname(urlPath))) return [];
|
|
227
|
+
return insideVendorTree(
|
|
228
|
+
vendorRoot,
|
|
229
|
+
gameIds.map((id) => join(vendorRoot, id, 'public', urlPath)),
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function send(res: import('node:http').ServerResponse, filePath: string, buf: Buffer): void {
|
|
234
|
+
res.setHeader('Content-Type', MIME[extname(filePath)] ?? 'application/octet-stream');
|
|
235
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
236
|
+
res.statusCode = 200;
|
|
237
|
+
res.end(buf);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Serve the first candidate that exists; `false` when none did (caller falls through). */
|
|
241
|
+
async function serveFirst(
|
|
242
|
+
res: import('node:http').ServerResponse,
|
|
243
|
+
candidates: readonly string[],
|
|
244
|
+
): Promise<boolean> {
|
|
245
|
+
for (const filePath of candidates) {
|
|
246
|
+
try {
|
|
247
|
+
send(res, filePath, await readFile(filePath));
|
|
248
|
+
return true;
|
|
249
|
+
} catch {
|
|
250
|
+
// try the next vendored game's public dir
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* ## Why the two routes sit on opposite sides of Vite
|
|
258
|
+
*
|
|
259
|
+
* `configureServer`'s BODY installs a middleware ahead of Vite's own; the function it
|
|
260
|
+
* RETURNS installs one after them (and, load-bearing here, still ahead of
|
|
261
|
+
* `indexHtmlMiddleware`). The id-carrying route is safe anywhere and stays in front. The
|
|
262
|
+
* root-relative fallback goes behind, which is what lets it claim `.json` without being able
|
|
263
|
+
* to shadow anything the editor owns: by the time it runs, Vite's transform, `/@fs/` and
|
|
264
|
+
* static routes have all declined.
|
|
265
|
+
*
|
|
266
|
+
* MEASURED, and the reason this split exists: with the fallback in front and media-only,
|
|
267
|
+
* bubbo-bubbo's atlas JSON fell past both routes to the SPA fallback and Pixi parsed
|
|
268
|
+
* `index.html` (`SyntaxError: Unexpected token '<'`). With it behind and `.json` allowed,
|
|
269
|
+
* the same request is answered from the game's own `public/`.
|
|
270
|
+
*
|
|
271
|
+
* The SPA fallback has already rewritten `req.url` to `/index.html` by then (Vite's
|
|
272
|
+
* `htmlFallbackMiddleware` does that unconditionally for an `Accept: * / *` GET), so the
|
|
273
|
+
* post route reads `req.originalUrl` — Express sets it before handing off, and it is the
|
|
274
|
+
* only place the game's real request survives.
|
|
275
|
+
*/
|
|
276
|
+
export function gameStaticPlugin(repoRoot: string): Plugin {
|
|
277
|
+
const vendorRoot = resolve(repoRoot, 'vendor/games');
|
|
278
|
+
const gameIds = discoverVendoredGameIds(vendorRoot);
|
|
279
|
+
return {
|
|
280
|
+
name: 'vgai-game-static',
|
|
281
|
+
configureServer(server) {
|
|
282
|
+
// AHEAD of Vite: the id-carrying `/vendor/games/<id>/…` route.
|
|
283
|
+
server.middlewares.use(async (req, res, next) => {
|
|
284
|
+
if (gameIds.length === 0) return next();
|
|
285
|
+
const url = (req.url ?? '').split('?')[0] ?? '';
|
|
286
|
+
if (await serveFirst(res, resolveVendoredPublicPath(vendorRoot, gameIds, url))) return;
|
|
287
|
+
next();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
// BEHIND Vite: the root-relative fallback.
|
|
291
|
+
return () => {
|
|
292
|
+
server.middlewares.use(async (req, res, next) => {
|
|
293
|
+
if (gameIds.length === 0) return next();
|
|
294
|
+
const raw = (req as { originalUrl?: string }).originalUrl ?? req.url ?? '';
|
|
295
|
+
const url = raw.split('?')[0] ?? '';
|
|
296
|
+
if (await serveFirst(res, resolveVendoredRootRelativePath(vendorRoot, gameIds, url)))
|
|
297
|
+
return;
|
|
298
|
+
next();
|
|
299
|
+
});
|
|
300
|
+
};
|
|
301
|
+
},
|
|
302
|
+
};
|
|
303
|
+
}
|