@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,544 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* R3F hierarchy reparent hardening — the PURE plan for "move this JSX element into
|
|
3
|
+
* that one", covering R1 (scope safety), R2 (world-transform preservation) and R3
|
|
4
|
+
* (destination legality) before a single byte is written.
|
|
5
|
+
*
|
|
6
|
+
* Why here: `plan-source-edit.ts` is the ONE place both tiers (dev server and hosted
|
|
7
|
+
* browser) route a source edit through, and its `reparent` case used to be a bare
|
|
8
|
+
* `reparentElement` — a textual line-block move that is sound only between two parents
|
|
9
|
+
* in the same lexical scope with identical accumulated transforms. The moment the
|
|
10
|
+
* hierarchy invites arbitrary drags it is unsound three ways, all of them SILENT:
|
|
11
|
+
*
|
|
12
|
+
* 1. Lexical capture — an element authored inside a component function may reference
|
|
13
|
+
* that function's own bindings (`color={tint}`, a `ref`, a mapped variable).
|
|
14
|
+
* Textually moving it elsewhere produces code that does not compile, or compiles
|
|
15
|
+
* against a DIFFERENT binding with the same name.
|
|
16
|
+
* 2. Transform re-basing — a verbatim move preserves the authored `position` tuple,
|
|
17
|
+
* not the world position. Between identity parents those are the same thing;
|
|
18
|
+
* between transformed parents the object teleports on the next mount.
|
|
19
|
+
* 3. Boundary blindness — a self-closing destination (which is what nearly every R3F
|
|
20
|
+
* component callsite is) made `reparentElement` insert a PRECEDING SIBLING instead
|
|
21
|
+
* of a child, and a destination rendered N times would author the element once and
|
|
22
|
+
* render it N times.
|
|
23
|
+
*
|
|
24
|
+
* The response to all three is the same and is the anti-shim rule: REFUSE, naming the
|
|
25
|
+
* thing that made the move unsafe. This module never rewrites an expression, never
|
|
26
|
+
* renames a binding, and never writes a computed value over an authored one — the
|
|
27
|
+
* literal-vs-dynamic guard is as sacred here as at the gizmo.
|
|
28
|
+
*
|
|
29
|
+
* R4 (one transaction) falls out of living here: every rule is decided before the first
|
|
30
|
+
* edit, a refusal returns the input string identity-equal, and an accepted move returns
|
|
31
|
+
* ONE new whole-file string (tuple rewrites + slot opening + the move), which the
|
|
32
|
+
* caller's existing whole-file snapshot inverse turns into a single undo step.
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
import ts from 'typescript';
|
|
36
|
+
import { parseAuthoringTsx } from './ts-ast';
|
|
37
|
+
import {
|
|
38
|
+
analyzeJsxAttributes,
|
|
39
|
+
findTagEnd,
|
|
40
|
+
isNumberTupleLiteral,
|
|
41
|
+
openChildrenSlot,
|
|
42
|
+
reparentElement,
|
|
43
|
+
type StructEditResult,
|
|
44
|
+
writePropChange,
|
|
45
|
+
} from './writer';
|
|
46
|
+
|
|
47
|
+
export type ReparentChannel = 'position' | 'rotation' | 'scale';
|
|
48
|
+
|
|
49
|
+
const CHANNELS: readonly ReparentChannel[] = ['position', 'rotation', 'scale'];
|
|
50
|
+
const NUMBER_RE = /^-?\d+(\.\d+)?$/;
|
|
51
|
+
const EPS = 1e-6;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* The new LOCAL transform channels that preserve the element's world transform under
|
|
55
|
+
* the destination parent — computed by the caller, which is the only side that knows
|
|
56
|
+
* the live parents (R2). Absent channels are left exactly as authored.
|
|
57
|
+
*/
|
|
58
|
+
export interface ReparentRebase {
|
|
59
|
+
readonly position?: readonly number[] | undefined;
|
|
60
|
+
readonly rotation?: readonly number[] | undefined;
|
|
61
|
+
readonly scale?: readonly number[] | undefined;
|
|
62
|
+
/** Channels whose native source spelling is scalar even when the live
|
|
63
|
+
* decomposition is carried as a one-value tuple (Pixi rotation). */
|
|
64
|
+
readonly scalarChannels?: readonly ReparentChannel[] | undefined;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ReparentOptions {
|
|
68
|
+
readonly rebase?: ReparentRebase | undefined;
|
|
69
|
+
/**
|
|
70
|
+
* How many live objects the DESTINATION's oid resolves to. More than one means the
|
|
71
|
+
* destination is authored once and rendered N times (a `.map`ped callsite, or a
|
|
72
|
+
* component definition with N instances), so the moved element would be authored
|
|
73
|
+
* once and rendered N times too — R3 refuses that with the count.
|
|
74
|
+
*/
|
|
75
|
+
readonly destinationInstances?: number | undefined;
|
|
76
|
+
/**
|
|
77
|
+
* The same count for the element being MOVED. More than one is the mirrored case and
|
|
78
|
+
* is ALLOWED (it is exactly the de-duplication refactor this feature exists for), so
|
|
79
|
+
* it produces a warning rather than a refusal.
|
|
80
|
+
*/
|
|
81
|
+
readonly sourceInstances?: number | undefined;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ReparentPlan extends StructEditResult {
|
|
85
|
+
/** The named reason the move was refused. Present iff `changed` is false and the
|
|
86
|
+
* input was left byte-identical because a rule said no. */
|
|
87
|
+
readonly error?: string;
|
|
88
|
+
/** Applied, but with something the author should know (R3's mirrored case). */
|
|
89
|
+
readonly warning?: string;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ---------------------------------------------------------------- source lookup
|
|
93
|
+
|
|
94
|
+
export type JsxElementNode = ts.JsxElement | ts.JsxSelfClosingElement;
|
|
95
|
+
|
|
96
|
+
/** The JSX element whose OPENING tag starts exactly at `offset` — the position basis
|
|
97
|
+
* every `OidEntry` uses. */
|
|
98
|
+
export function jsxElementAt(sf: ts.SourceFile, offset: number): JsxElementNode | null {
|
|
99
|
+
let found: JsxElementNode | null = null;
|
|
100
|
+
const visit = (node: ts.Node): void => {
|
|
101
|
+
if (found) return;
|
|
102
|
+
// A node that ends at or before `offset`, or begins after it, cannot contain an
|
|
103
|
+
// element STARTING at `offset` — prune both directions.
|
|
104
|
+
if (node.getEnd() <= offset || node.getStart(sf) > offset) return;
|
|
105
|
+
if (ts.isJsxSelfClosingElement(node) && node.getStart(sf) === offset) {
|
|
106
|
+
found = node;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (ts.isJsxElement(node) && node.openingElement.getStart(sf) === offset) {
|
|
110
|
+
found = node;
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
ts.forEachChild(node, visit);
|
|
114
|
+
};
|
|
115
|
+
visit(sf);
|
|
116
|
+
return found;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function openingTagOf(node: JsxElementNode): ts.JsxOpeningElement | ts.JsxSelfClosingElement {
|
|
120
|
+
return ts.isJsxElement(node) ? node.openingElement : node;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function tagTextOf(node: JsxElementNode, sf: ts.SourceFile): string {
|
|
124
|
+
return openingTagOf(node).tagName.getText(sf);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function contains(outer: ts.Node, sf: ts.SourceFile, offset: number): boolean {
|
|
128
|
+
return outer.getStart(sf) <= offset && offset < outer.getEnd();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ------------------------------------------------------------- R1: scope safety
|
|
132
|
+
|
|
133
|
+
/** Every name a declaration binds, flattened through destructuring patterns. */
|
|
134
|
+
function boundNames(name: ts.BindingName, into: Set<string>): void {
|
|
135
|
+
if (ts.isIdentifier(name)) {
|
|
136
|
+
into.add(name.text);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
for (const element of name.elements) {
|
|
140
|
+
if (ts.isOmittedExpression(element)) continue;
|
|
141
|
+
boundNames(element.name, into);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function declaredByStatement(statement: ts.Statement, into: Set<string>): void {
|
|
146
|
+
if (ts.isVariableStatement(statement)) {
|
|
147
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
148
|
+
boundNames(declaration.name, into);
|
|
149
|
+
}
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
if (ts.isFunctionDeclaration(statement) && statement.name) into.add(statement.name.text);
|
|
153
|
+
else if (ts.isClassDeclaration(statement) && statement.name) into.add(statement.name.text);
|
|
154
|
+
else if (ts.isImportDeclaration(statement) && statement.importClause) {
|
|
155
|
+
const clause = statement.importClause;
|
|
156
|
+
if (clause.name) into.add(clause.name.text);
|
|
157
|
+
const bindings = clause.namedBindings;
|
|
158
|
+
if (bindings && ts.isNamespaceImport(bindings)) into.add(bindings.name.text);
|
|
159
|
+
else if (bindings && ts.isNamedImports(bindings)) {
|
|
160
|
+
for (const element of bindings.elements) into.add(element.name.text);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/** The names a single scope-introducing node binds, or null when it is not a scope. */
|
|
166
|
+
function scopeBindings(node: ts.Node): Set<string> | null {
|
|
167
|
+
const names = new Set<string>();
|
|
168
|
+
if (ts.isSourceFile(node)) {
|
|
169
|
+
for (const statement of node.statements) declaredByStatement(statement, names);
|
|
170
|
+
return names;
|
|
171
|
+
}
|
|
172
|
+
if (ts.isBlock(node) || ts.isModuleBlock(node) || ts.isCaseBlock(node)) {
|
|
173
|
+
const statements = ts.isCaseBlock(node)
|
|
174
|
+
? node.clauses.flatMap((clause) => [...clause.statements])
|
|
175
|
+
: [...node.statements];
|
|
176
|
+
for (const statement of statements) declaredByStatement(statement, names);
|
|
177
|
+
return names;
|
|
178
|
+
}
|
|
179
|
+
if (
|
|
180
|
+
ts.isFunctionDeclaration(node) ||
|
|
181
|
+
ts.isFunctionExpression(node) ||
|
|
182
|
+
ts.isArrowFunction(node) ||
|
|
183
|
+
ts.isMethodDeclaration(node) ||
|
|
184
|
+
ts.isConstructorDeclaration(node) ||
|
|
185
|
+
ts.isGetAccessor(node) ||
|
|
186
|
+
ts.isSetAccessor(node)
|
|
187
|
+
) {
|
|
188
|
+
for (const parameter of node.parameters) boundNames(parameter.name, names);
|
|
189
|
+
if ((ts.isFunctionDeclaration(node) || ts.isFunctionExpression(node)) && node.name) {
|
|
190
|
+
names.add(node.name.text);
|
|
191
|
+
}
|
|
192
|
+
return names;
|
|
193
|
+
}
|
|
194
|
+
if (ts.isForStatement(node) || ts.isForOfStatement(node) || ts.isForInStatement(node)) {
|
|
195
|
+
const initializer = node.initializer;
|
|
196
|
+
if (initializer && ts.isVariableDeclarationList(initializer)) {
|
|
197
|
+
for (const declaration of initializer.declarations) boundNames(declaration.name, names);
|
|
198
|
+
}
|
|
199
|
+
return names;
|
|
200
|
+
}
|
|
201
|
+
if (ts.isCatchClause(node)) {
|
|
202
|
+
if (node.variableDeclaration) boundNames(node.variableDeclaration.name, names);
|
|
203
|
+
return names;
|
|
204
|
+
}
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** The innermost enclosing scope of `from` that binds `name`, or null when nothing
|
|
209
|
+
* in the lexical chain does (a global, or an unresolved reference — either way not a
|
|
210
|
+
* capture this move can break). */
|
|
211
|
+
export function bindingScopeOf(name: string, from: ts.Node): ts.Node | null {
|
|
212
|
+
let cursor: ts.Node | undefined = from;
|
|
213
|
+
while (cursor) {
|
|
214
|
+
const bindings = scopeBindings(cursor);
|
|
215
|
+
if (bindings?.has(name)) return cursor;
|
|
216
|
+
cursor = cursor.parent;
|
|
217
|
+
}
|
|
218
|
+
return null;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/** The nearest named function around `node` — what a refusal calls the owner. */
|
|
222
|
+
export function owningFunctionName(node: ts.Node, sf: ts.SourceFile): string {
|
|
223
|
+
let cursor: ts.Node | undefined = node;
|
|
224
|
+
while (cursor) {
|
|
225
|
+
if (ts.isFunctionDeclaration(cursor) && cursor.name) return cursor.name.text;
|
|
226
|
+
if (
|
|
227
|
+
(ts.isArrowFunction(cursor) || ts.isFunctionExpression(cursor)) &&
|
|
228
|
+
cursor.parent &&
|
|
229
|
+
ts.isVariableDeclaration(cursor.parent) &&
|
|
230
|
+
ts.isIdentifier(cursor.parent.name)
|
|
231
|
+
) {
|
|
232
|
+
return cursor.parent.name.text;
|
|
233
|
+
}
|
|
234
|
+
cursor = cursor.parent;
|
|
235
|
+
}
|
|
236
|
+
return ts.isSourceFile(node) ? 'this module' : `this scope (line ${lineOf(node, sf)})`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function lineOf(node: ts.Node, sf: ts.SourceFile): number {
|
|
240
|
+
return sf.getLineAndCharacterOfPosition(node.getStart(sf)).line + 1;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* The identifiers the element's JSX subtree REFERENCES from outside itself — the R1
|
|
245
|
+
* input. Same machinery as the contract analyzer (a plain `ts` walk over the TSX AST).
|
|
246
|
+
*
|
|
247
|
+
* It counts an identifier it is unsure about, so an unrecognized shape refuses rather
|
|
248
|
+
* than moves. The one deliberate subtraction is names the subtree binds FOR ITSELF —
|
|
249
|
+
* without it, a `.map((angle) => …)` inside the moved element would read as a capture
|
|
250
|
+
* of the outer scope and nothing containing a mapped list could ever move. Stated
|
|
251
|
+
* plainly, because it is not free: a name bound inside the subtree in one place and
|
|
252
|
+
* captured from outside it in another is subtracted too, and that capture is missed.
|
|
253
|
+
* A tighter answer needs a real binder, not a name set; this is the honest limit of
|
|
254
|
+
* the cheap one.
|
|
255
|
+
*/
|
|
256
|
+
export function referencedIdentifiers(node: JsxElementNode): Map<string, ts.Node> {
|
|
257
|
+
const referenced = new Map<string, ts.Node>();
|
|
258
|
+
const localBindings = new Set<string>();
|
|
259
|
+
|
|
260
|
+
const visit = (current: ts.Node): void => {
|
|
261
|
+
// Types name types, not values — a moved element's `as THREE.Group` is not a
|
|
262
|
+
// runtime capture.
|
|
263
|
+
if (ts.isTypeNode(current) || ts.isTypeParameterDeclaration(current)) return;
|
|
264
|
+
|
|
265
|
+
const nested = scopeBindings(current);
|
|
266
|
+
if (nested && current !== node) for (const name of nested) localBindings.add(name);
|
|
267
|
+
|
|
268
|
+
if (ts.isPropertyAccessExpression(current)) {
|
|
269
|
+
visit(current.expression); // `a.b.c` references `a` only
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
if (ts.isJsxAttribute(current)) {
|
|
273
|
+
if (current.initializer) visit(current.initializer);
|
|
274
|
+
return; // the attribute NAME is not an identifier reference
|
|
275
|
+
}
|
|
276
|
+
if (ts.isPropertyAssignment(current)) {
|
|
277
|
+
if (ts.isComputedPropertyName(current.name)) visit(current.name);
|
|
278
|
+
visit(current.initializer);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
if (ts.isJsxOpeningElement(current) || ts.isJsxSelfClosingElement(current)) {
|
|
282
|
+
// A lowercase host tag (`<mesh>`) is an intrinsic element, not a binding. A
|
|
283
|
+
// capitalized or dotted one resolves through the lexical scope like any value.
|
|
284
|
+
const tag = current.tagName;
|
|
285
|
+
const root = ts.isPropertyAccessExpression(tag) ? leftmostIdentifier(tag) : tag;
|
|
286
|
+
if (ts.isIdentifier(root) && /^[A-Z_$]/.test(root.text) && !referenced.has(root.text)) {
|
|
287
|
+
referenced.set(root.text, root);
|
|
288
|
+
}
|
|
289
|
+
for (const property of current.attributes.properties) visit(property);
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (ts.isJsxClosingElement(current)) return;
|
|
293
|
+
if (ts.isIdentifier(current)) {
|
|
294
|
+
if (!referenced.has(current.text)) referenced.set(current.text, current);
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
ts.forEachChild(current, visit);
|
|
298
|
+
};
|
|
299
|
+
visit(node);
|
|
300
|
+
|
|
301
|
+
for (const name of localBindings) referenced.delete(name);
|
|
302
|
+
return referenced;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function leftmostIdentifier(node: ts.PropertyAccessExpression): ts.Node {
|
|
306
|
+
let cursor: ts.Node = node;
|
|
307
|
+
while (ts.isPropertyAccessExpression(cursor)) cursor = cursor.expression;
|
|
308
|
+
return cursor;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// -------------------------------------------------- R3: destination legality
|
|
312
|
+
|
|
313
|
+
type ChildrenSlot = 'paired' | 'expandable';
|
|
314
|
+
|
|
315
|
+
/** Does a component DEFINED IN THIS FILE render whatever children a callsite gives it?
|
|
316
|
+
* Proven, never guessed: it either names `children` (destructured or `props.children`)
|
|
317
|
+
* or spreads its props object onto a host element. */
|
|
318
|
+
function componentForwardsChildren(sf: ts.SourceFile, name: string): boolean | 'undefined' {
|
|
319
|
+
const definition = findComponentDefinition(sf, name);
|
|
320
|
+
if (!definition) return 'undefined';
|
|
321
|
+
const parameter = definition.parameters[0];
|
|
322
|
+
const spreadable = new Set<string>();
|
|
323
|
+
let bindsChildren = false;
|
|
324
|
+
if (parameter) {
|
|
325
|
+
if (ts.isIdentifier(parameter.name)) spreadable.add(parameter.name.text);
|
|
326
|
+
else if (ts.isObjectBindingPattern(parameter.name)) {
|
|
327
|
+
for (const element of parameter.name.elements) {
|
|
328
|
+
const propertyName = (element.propertyName ?? element.name).getText(sf);
|
|
329
|
+
if (propertyName === 'children') bindsChildren = true;
|
|
330
|
+
if (element.dotDotDotToken && ts.isIdentifier(element.name)) {
|
|
331
|
+
spreadable.add(element.name.text);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
if (bindsChildren) return true;
|
|
337
|
+
|
|
338
|
+
let forwards = false;
|
|
339
|
+
const visit = (node: ts.Node): void => {
|
|
340
|
+
if (forwards) return;
|
|
341
|
+
if (ts.isJsxSpreadAttribute(node)) {
|
|
342
|
+
const expression = node.expression;
|
|
343
|
+
if (ts.isIdentifier(expression) && spreadable.has(expression.text)) forwards = true;
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
if (ts.isPropertyAccessExpression(node) && node.name.text === 'children') {
|
|
347
|
+
if (ts.isIdentifier(node.expression) && spreadable.has(node.expression.text)) {
|
|
348
|
+
forwards = true;
|
|
349
|
+
}
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
ts.forEachChild(node, visit);
|
|
353
|
+
};
|
|
354
|
+
if (definition.body) visit(definition.body);
|
|
355
|
+
return forwards;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function findComponentDefinition(
|
|
359
|
+
sf: ts.SourceFile,
|
|
360
|
+
name: string,
|
|
361
|
+
): ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression | null {
|
|
362
|
+
let found: ts.FunctionDeclaration | ts.ArrowFunction | ts.FunctionExpression | null = null;
|
|
363
|
+
const visit = (node: ts.Node): void => {
|
|
364
|
+
if (found) return;
|
|
365
|
+
if (ts.isFunctionDeclaration(node) && node.name?.text === name) {
|
|
366
|
+
found = node;
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (
|
|
370
|
+
ts.isVariableDeclaration(node) &&
|
|
371
|
+
ts.isIdentifier(node.name) &&
|
|
372
|
+
node.name.text === name &&
|
|
373
|
+
node.initializer &&
|
|
374
|
+
(ts.isArrowFunction(node.initializer) || ts.isFunctionExpression(node.initializer))
|
|
375
|
+
) {
|
|
376
|
+
found = node.initializer;
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
ts.forEachChild(node, visit);
|
|
380
|
+
};
|
|
381
|
+
visit(sf);
|
|
382
|
+
return found;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// ------------------------------------------------------------------- the plan
|
|
386
|
+
|
|
387
|
+
function fmt(value: number): string {
|
|
388
|
+
const rounded = Math.round(value * 1e4) / 1e4;
|
|
389
|
+
return Object.is(rounded, -0) ? '0' : String(rounded);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function tupleText(values: readonly number[]): string {
|
|
393
|
+
return `[${values.map(fmt).join(', ')}]`;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Plan a same-file reparent. `elementStart` and `parentStart` are the `<` offsets the
|
|
398
|
+
* OID index resolves to; `options` carries what only the live scene knows.
|
|
399
|
+
*
|
|
400
|
+
* Returns the input string unchanged (identity, so a caller comparing bytes sees no
|
|
401
|
+
* diff) plus a named `error` for every refusal.
|
|
402
|
+
*/
|
|
403
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: one gate per numbered rule, in the order the spec states them; splitting it would hide the "plan everything before writing anything" invariant this function exists to hold.
|
|
404
|
+
export function planReparent(
|
|
405
|
+
code: string,
|
|
406
|
+
elementStart: number,
|
|
407
|
+
parentStart: number,
|
|
408
|
+
options: ReparentOptions = {},
|
|
409
|
+
): ReparentPlan {
|
|
410
|
+
const refuse = (error: string): ReparentPlan => ({ code, changed: false, error });
|
|
411
|
+
const sf = parseAuthoringTsx('reparent.tsx', code);
|
|
412
|
+
const element = jsxElementAt(sf, elementStart);
|
|
413
|
+
const destination = jsxElementAt(sf, parentStart);
|
|
414
|
+
if (!element) return refuse('the moved element is no longer at its indexed source position.');
|
|
415
|
+
if (!destination) {
|
|
416
|
+
return refuse('the destination is no longer at its indexed source position.');
|
|
417
|
+
}
|
|
418
|
+
const elementTag = tagTextOf(element, sf);
|
|
419
|
+
const destinationTag = tagTextOf(destination, sf);
|
|
420
|
+
if (element === destination) return refuse(`<${elementTag}> cannot be its own parent.`);
|
|
421
|
+
if (contains(element, sf, parentStart)) {
|
|
422
|
+
return refuse(`<${destinationTag}> is inside <${elementTag}> — a move there would be a cycle.`);
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// --- R3: destination legality ------------------------------------------------
|
|
426
|
+
const destinationInstances = options.destinationInstances;
|
|
427
|
+
if (destinationInstances !== undefined && destinationInstances > 1) {
|
|
428
|
+
return refuse(
|
|
429
|
+
`${destinationTag} renders ${destinationInstances} times; moving this into it would ` +
|
|
430
|
+
`author it once and render it ${destinationInstances} times.`,
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
const slot: ChildrenSlot = ts.isJsxElement(destination) ? 'paired' : 'expandable';
|
|
434
|
+
if (/^[A-Z_$]/.test(destinationTag) || destinationTag.includes('.')) {
|
|
435
|
+
const forwards = componentForwardsChildren(sf, destinationTag);
|
|
436
|
+
if (forwards === 'undefined') {
|
|
437
|
+
return refuse(
|
|
438
|
+
`${destinationTag} is not defined in this file — the editor cannot prove it renders ` +
|
|
439
|
+
'its children into the world, so it refuses to move anything inside it.',
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
if (!forwards) {
|
|
443
|
+
return refuse(
|
|
444
|
+
`${destinationTag} does not render children — nothing can be authored inside it.`,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
// --- R1: scope safety --------------------------------------------------------
|
|
450
|
+
for (const [name, reference] of referencedIdentifiers(element)) {
|
|
451
|
+
const scope = bindingScopeOf(name, reference);
|
|
452
|
+
if (!scope || contains(scope, sf, parentStart)) continue;
|
|
453
|
+
return refuse(
|
|
454
|
+
`<${elementTag}> references '${name}', which only exists inside ` +
|
|
455
|
+
`${owningFunctionName(scope, sf)}.`,
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// --- R2: world-transform preservation ---------------------------------------
|
|
460
|
+
const rebase = options.rebase;
|
|
461
|
+
const tagEnd = findTagEnd(code, elementStart);
|
|
462
|
+
if (tagEnd < 0) return refuse(`<${elementTag}>'s opening tag could not be read.`);
|
|
463
|
+
const attrs = analyzeJsxAttributes(code, elementStart, tagEnd);
|
|
464
|
+
const pending: Array<{ channel: ReparentChannel; values: readonly number[]; scalar: boolean }> =
|
|
465
|
+
[];
|
|
466
|
+
for (const channel of CHANNELS) {
|
|
467
|
+
const values = rebase?.[channel];
|
|
468
|
+
if (!values) continue;
|
|
469
|
+
const attr = attrs.find((candidate) => candidate.name === channel);
|
|
470
|
+
if (attr) {
|
|
471
|
+
const scalar =
|
|
472
|
+
(attr.isExpression && NUMBER_RE.test(attr.rawValue)) ||
|
|
473
|
+
rebase?.scalarChannels?.includes(channel) === true;
|
|
474
|
+
const tuple = attr.isExpression && isNumberTupleLiteral(attr.rawValue);
|
|
475
|
+
if (!scalar && !tuple) {
|
|
476
|
+
return refuse(
|
|
477
|
+
`preserving <${elementTag}>'s world transform needs a new ${channel}, but ` +
|
|
478
|
+
`${channel} is bound to the expression {${attr.rawValue}} — the editor will not ` +
|
|
479
|
+
'write a tuple over an expression.',
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
pending.push({ channel, values, scalar });
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
pending.push({
|
|
486
|
+
channel,
|
|
487
|
+
values,
|
|
488
|
+
scalar: rebase?.scalarChannels?.includes(channel) === true,
|
|
489
|
+
});
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
// --- R4: everything above decided; only now does anything get written --------
|
|
493
|
+
let next = code;
|
|
494
|
+
for (const { channel, values, scalar } of pending) {
|
|
495
|
+
const uniform =
|
|
496
|
+
values.length === 3 &&
|
|
497
|
+
Math.abs((values[0] ?? 0) - (values[1] ?? 0)) < EPS &&
|
|
498
|
+
Math.abs((values[1] ?? 0) - (values[2] ?? 0)) < EPS;
|
|
499
|
+
const text =
|
|
500
|
+
scalar && (values.length === 1 || uniform) ? fmt(values[0] ?? 0) : tupleText(values);
|
|
501
|
+
const written = writePropChange(next, elementStart, channel, text, {
|
|
502
|
+
addIfMissing: true,
|
|
503
|
+
allowShapeUpgrade: scalar,
|
|
504
|
+
});
|
|
505
|
+
if (written.dynamic) {
|
|
506
|
+
return refuse(
|
|
507
|
+
`preserving <${elementTag}>'s world transform needs a new ${channel}, but ${channel} ` +
|
|
508
|
+
'is expression-bound.',
|
|
509
|
+
);
|
|
510
|
+
}
|
|
511
|
+
next = written.code;
|
|
512
|
+
}
|
|
513
|
+
// Every tuple rewrite lands strictly inside the moved element's own opening tag, and
|
|
514
|
+
// the destination cannot be inside that element (the cycle gate above), so a
|
|
515
|
+
// destination LATER in the file shifts by exactly the bytes those rewrites added.
|
|
516
|
+
let movedStart = elementStart;
|
|
517
|
+
const destinationStart =
|
|
518
|
+
parentStart > elementStart ? parentStart + (next.length - code.length) : parentStart;
|
|
519
|
+
|
|
520
|
+
if (slot === 'expandable') {
|
|
521
|
+
const opened = openChildrenSlot(next, destinationStart);
|
|
522
|
+
if (!opened.changed) {
|
|
523
|
+
return refuse(`<${destinationTag} /> could not be opened to receive a child.`);
|
|
524
|
+
}
|
|
525
|
+
const grew = opened.code.length - next.length;
|
|
526
|
+
next = opened.code;
|
|
527
|
+
if (movedStart > destinationStart) movedStart += grew;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const moved = reparentElement(next, movedStart, destinationStart);
|
|
531
|
+
if (!moved.changed) return refuse(`<${elementTag}> could not be moved into <${destinationTag}>.`);
|
|
532
|
+
|
|
533
|
+
const sourceInstances = options.sourceInstances;
|
|
534
|
+
const warning =
|
|
535
|
+
sourceInstances !== undefined && sourceInstances > 1
|
|
536
|
+
? `${elementTag} was authored once and rendered ${sourceInstances} times; moving it out ` +
|
|
537
|
+
`leaves ${sourceInstances - 1} of those renders without it.`
|
|
538
|
+
: undefined;
|
|
539
|
+
return {
|
|
540
|
+
code: moved.code,
|
|
541
|
+
changed: true,
|
|
542
|
+
...(warning ? { warning } : {}),
|
|
543
|
+
};
|
|
544
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SOURCE-EDIT REQUEST — the one wire shape a source edit is stated in, and
|
|
3
|
+
* deliberately its own file.
|
|
4
|
+
*
|
|
5
|
+
* It sits between two programs that must NOT share a type graph: the browser
|
|
6
|
+
* editor (`ui-source/source-write-backend.ts`, which posts it) and the NODE
|
|
7
|
+
* dev server (`vite-plugin-ui-oid.ts`'s middleware and `ui-source/plan-source-edit.ts`,
|
|
8
|
+
* which plan and apply it). Until 2026-09-20 both sides imported the type from
|
|
9
|
+
* `source-write-backend.ts` — and that module value-imports `files/project-files.ts`,
|
|
10
|
+
* which reaches `storage/` and from there the editor SHELL STORE, so
|
|
11
|
+
* `tsconfig.server.json` compiled 231 browser modules including 36 React ones to
|
|
12
|
+
* typecheck a Node program (the fourth blind review's "the Node server's type graph
|
|
13
|
+
* now reaching the browser app"; the config's own header recorded the 310 errors
|
|
14
|
+
* that forced its `paths` and `jsx` settings).
|
|
15
|
+
*
|
|
16
|
+
* So: the REQUEST lives here, importing nothing but its two sibling AST types, and
|
|
17
|
+
* `source-write-backend.ts` re-exports it for the browser callers that already name
|
|
18
|
+
* it. Anything added to this file must stay free of browser and Node imports alike —
|
|
19
|
+
* it is read by both.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import type { ReparentRebase } from './reparent-guard';
|
|
23
|
+
import type { DuplicateRewrite } from './writer';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* What only the LIVE scene knows about a `reparent`, carried on the request so the
|
|
27
|
+
* pure planner (`reparent-guard.ts`) can decide R2/R3 without a scene of its own.
|
|
28
|
+
*
|
|
29
|
+
* Every field is optional and every one of them can only make the plan MORE strict:
|
|
30
|
+
* the planner's source-derivable rules (scope safety, children slot, literal-vs-
|
|
31
|
+
* dynamic) run identically whether or not a caller supplies them, so a client that
|
|
32
|
+
* knows nothing still gets a sound refusal rather than a silent corruption.
|
|
33
|
+
*/
|
|
34
|
+
export interface StructReparentContext {
|
|
35
|
+
/** The new LOCAL transform that preserves the element's world transform under the
|
|
36
|
+
* destination — the caller computed it from the two live parents (R2). */
|
|
37
|
+
rebase?: ReparentRebase;
|
|
38
|
+
/** Live objects the destination oid resolves to; >1 is refused with the count (R3). */
|
|
39
|
+
destinationInstances?: number;
|
|
40
|
+
/** Live objects the moved element's oid resolves to; >1 warns and is allowed (R3). */
|
|
41
|
+
sourceInstances?: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export type SourceEditRequest =
|
|
45
|
+
/** `value` is a NUMBER for a numeric CSS property, and that is load-bearing:
|
|
46
|
+
* the writer emits a bare `12` (which React px-ifies at render) rather than
|
|
47
|
+
* the quoted `'12'` the CSSOM rejects. `null` is the REMOVAL sentinel. */
|
|
48
|
+
| { kind: 'style'; oid: string; prop: string; value: string | number | null }
|
|
49
|
+
| { kind: 'css'; file: string; selector: string; prop: string; value: string; media?: string }
|
|
50
|
+
| { kind: 'text'; oid: string; text: string }
|
|
51
|
+
| {
|
|
52
|
+
kind: 'prop';
|
|
53
|
+
oid: string;
|
|
54
|
+
prop: string;
|
|
55
|
+
/** `null` is the REMOVAL sentinel — the same shape `style` uses (D-A3);
|
|
56
|
+
* it routes to `removePropAttribute` instead of a value write. */
|
|
57
|
+
value: string | null;
|
|
58
|
+
addIfMissing?: boolean;
|
|
59
|
+
allowShapeUpgrade?: boolean;
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
/** Replace a literal default in the component declaration containing
|
|
63
|
+
* `oid`. The component name comes from the OID index, never the caller. */
|
|
64
|
+
kind: 'component-default';
|
|
65
|
+
oid: string;
|
|
66
|
+
prop: string;
|
|
67
|
+
value: string;
|
|
68
|
+
}
|
|
69
|
+
| ({
|
|
70
|
+
kind: 'struct';
|
|
71
|
+
oid: string;
|
|
72
|
+
op: string;
|
|
73
|
+
targetOid?: string;
|
|
74
|
+
parentOid?: string;
|
|
75
|
+
wrapperTag?: string;
|
|
76
|
+
/** Optional multi-line JSX snippet for `create`/`create-sibling` — see
|
|
77
|
+
* `insertChildElement` / `insertSiblingElement`. */
|
|
78
|
+
snippet?: string;
|
|
79
|
+
/** A named import the inserted `snippet` needs (its tag is a component).
|
|
80
|
+
* Applied to the SAME file in the same plan, so the insert and the import
|
|
81
|
+
* it depends on are one write and one undo entry — see `ensureNamedImport`. */
|
|
82
|
+
ensureImport?: { name: string; module: string; kind?: 'default' | 'named' };
|
|
83
|
+
/** `duplicate` only — what the copy should differ in (`writer.ts` `DuplicateRewrite`). */
|
|
84
|
+
duplicate?: DuplicateRewrite;
|
|
85
|
+
} & StructReparentContext)
|
|
86
|
+
| { kind: 'struct-many'; oids: readonly string[]; op: string; wrapperTag?: string };
|
|
87
|
+
|
|
88
|
+
export interface PreparedSourceEdit {
|
|
89
|
+
readonly changed: boolean;
|
|
90
|
+
readonly file?: string;
|
|
91
|
+
readonly resourcePath?: string;
|
|
92
|
+
readonly prevSource?: string;
|
|
93
|
+
readonly newSource?: string;
|
|
94
|
+
readonly prevSha?: string;
|
|
95
|
+
readonly newSha?: string;
|
|
96
|
+
readonly result: Record<string, unknown>;
|
|
97
|
+
}
|