@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,124 @@
|
|
|
1
|
+
import { isContainedRelativePath } from '@volter/editor-sdk/session/relative-path-guard';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
|
|
4
|
+
export const assetImportSettingsSchema = z
|
|
5
|
+
.object({
|
|
6
|
+
scale: z.number().positive().default(1),
|
|
7
|
+
sourceUnits: z.enum(['auto', 'mm', 'cm', 'm', 'in', 'ft']).default('auto'),
|
|
8
|
+
upAxis: z.enum(['auto', 'x', 'y', 'z']).default('auto'),
|
|
9
|
+
forwardAxis: z.enum(['auto', 'x', '-x', 'y', '-y', 'z', '-z']).default('auto'),
|
|
10
|
+
normals: z.enum(['preserve', 'generate', 'recalculate']).default('preserve'),
|
|
11
|
+
tangents: z.enum(['preserve', 'generate', 'discard']).default('preserve'),
|
|
12
|
+
materials: z.enum(['import', 'discard']).default('import'),
|
|
13
|
+
textures: z.enum(['copy', 'embed', 'discard']).default('copy'),
|
|
14
|
+
animations: z.array(z.string()).default([]),
|
|
15
|
+
meshOptimization: z.enum(['none', 'safe', 'aggressive']).default('safe'),
|
|
16
|
+
retainSource: z.boolean().default(true),
|
|
17
|
+
})
|
|
18
|
+
.strict();
|
|
19
|
+
export type AssetImportSettings = z.infer<typeof assetImportSettingsSchema>;
|
|
20
|
+
|
|
21
|
+
const safePathSchema = z
|
|
22
|
+
.string()
|
|
23
|
+
.min(1)
|
|
24
|
+
.refine(isContainedRelativePath, 'Path must stay within the source/project root.');
|
|
25
|
+
|
|
26
|
+
const importFileSchema = z
|
|
27
|
+
.object({
|
|
28
|
+
path: safePathSchema,
|
|
29
|
+
url: z.string().min(1),
|
|
30
|
+
hash: z.string().min(8),
|
|
31
|
+
size: z.number().int().nonnegative(),
|
|
32
|
+
role: z.enum(['primary', 'dependency', 'material', 'texture']),
|
|
33
|
+
})
|
|
34
|
+
.strict();
|
|
35
|
+
|
|
36
|
+
export const assetImportPlanSchema = z
|
|
37
|
+
.object({
|
|
38
|
+
version: z.literal(1),
|
|
39
|
+
id: z.string().min(1),
|
|
40
|
+
identity: z
|
|
41
|
+
.object({
|
|
42
|
+
familyId: z.string().min(1),
|
|
43
|
+
variantId: z.string().min(1),
|
|
44
|
+
deliveryId: z.string().min(1),
|
|
45
|
+
source: z.string().min(1).optional(),
|
|
46
|
+
displayName: z.string().min(1).optional(),
|
|
47
|
+
})
|
|
48
|
+
.strict(),
|
|
49
|
+
sourceFiles: z.array(importFileSchema).min(1),
|
|
50
|
+
generatedFiles: z.array(safePathSchema),
|
|
51
|
+
destination: safePathSchema,
|
|
52
|
+
contentKind: z
|
|
53
|
+
.enum(['model', 'animation-only', 'image', 'audio', 'material', 'data'])
|
|
54
|
+
.default('model'),
|
|
55
|
+
targetSkeleton: z.string().optional(),
|
|
56
|
+
settings: assetImportSettingsSchema,
|
|
57
|
+
conflicts: z.array(
|
|
58
|
+
z
|
|
59
|
+
.object({ path: z.string(), resolution: z.enum(['reuse', 'update', 'rename', 'cancel']) })
|
|
60
|
+
.strict(),
|
|
61
|
+
),
|
|
62
|
+
attribution: z
|
|
63
|
+
.object({
|
|
64
|
+
sourceUrl: z.string(),
|
|
65
|
+
author: z.string(),
|
|
66
|
+
license: z.string(),
|
|
67
|
+
text: z.string(),
|
|
68
|
+
})
|
|
69
|
+
.strict(),
|
|
70
|
+
sourceHash: z.string().min(8),
|
|
71
|
+
runtimeReady: z.boolean(),
|
|
72
|
+
backend: z.enum(['native', 'three', 'blender']),
|
|
73
|
+
createdAt: z.string(),
|
|
74
|
+
})
|
|
75
|
+
.superRefine((plan, context) => {
|
|
76
|
+
if (plan.contentKind === 'animation-only' && plan.runtimeReady && !plan.targetSkeleton) {
|
|
77
|
+
context.addIssue({
|
|
78
|
+
code: 'custom',
|
|
79
|
+
path: ['targetSkeleton'],
|
|
80
|
+
message: 'Runtime-ready animation-only imports require a compatible target skeleton.',
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
export type AssetImportPlan = z.infer<typeof assetImportPlanSchema>;
|
|
85
|
+
|
|
86
|
+
export const assetImportResultSchema = z
|
|
87
|
+
.object({
|
|
88
|
+
version: z.literal(1),
|
|
89
|
+
planId: z.string(),
|
|
90
|
+
status: z.enum(['imported', 'skipped', 'failed', 'cancelled']),
|
|
91
|
+
writtenFiles: z.array(
|
|
92
|
+
z
|
|
93
|
+
.object({ path: z.string(), hash: z.string(), size: z.number().int().nonnegative() })
|
|
94
|
+
.strict(),
|
|
95
|
+
),
|
|
96
|
+
skippedFiles: z.array(z.string()),
|
|
97
|
+
issues: z.array(
|
|
98
|
+
z.object({ code: z.string(), stage: z.string(), message: z.string() }).strict(),
|
|
99
|
+
),
|
|
100
|
+
})
|
|
101
|
+
.strict();
|
|
102
|
+
export type AssetImportResult = z.infer<typeof assetImportResultSchema>;
|
|
103
|
+
|
|
104
|
+
export type AssetImportStage = 'fetch' | 'convert' | 'validate' | 'commit';
|
|
105
|
+
export interface AssetImportProgress {
|
|
106
|
+
stage: AssetImportStage;
|
|
107
|
+
item: string;
|
|
108
|
+
loaded: number;
|
|
109
|
+
total: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export type AssetConflictKind =
|
|
113
|
+
| 'same-identity-same-hash'
|
|
114
|
+
| 'same-identity-updated'
|
|
115
|
+
| 'different-identity-same-name'
|
|
116
|
+
| 'user-edited-output';
|
|
117
|
+
export function safeConflictResolution(
|
|
118
|
+
kind: AssetConflictKind,
|
|
119
|
+
): 'reuse' | 'update' | 'rename' | 'cancel' {
|
|
120
|
+
if (kind === 'same-identity-same-hash') return 'reuse';
|
|
121
|
+
if (kind === 'same-identity-updated') return 'update';
|
|
122
|
+
if (kind === 'different-identity-same-name') return 'rename';
|
|
123
|
+
return 'cancel';
|
|
124
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two mechanical halves of "a read-modify-write of one file never loses a
|
|
3
|
+
* record", shared by the ledger's two I/O sides (`../../server/
|
|
4
|
+
* asset-ledger-store.ts` over `node:fs`, `./asset-ledger-backend.ts` over a
|
|
5
|
+
* `StorageBackend`).
|
|
6
|
+
*
|
|
7
|
+
* Why the ledger needs this at all: `.vgai/assets.json` (D-AP3) is updated by
|
|
8
|
+
* READING it, adding one entry, and writing the whole object back. Two of those
|
|
9
|
+
* in flight interleave — both read the old object, the later write wins, and the
|
|
10
|
+
* earlier record is gone with no error anywhere. Two materializations at once is
|
|
11
|
+
* ordinary, not exotic: two `vgai edit` sessions on one project, `npm run
|
|
12
|
+
* asset-packs:sync` while an editor is prewarming, two tabs on one project
|
|
13
|
+
* both retrying their declared packs on reopen.
|
|
14
|
+
*
|
|
15
|
+
* Neither half alone is enough, which is why both are here:
|
|
16
|
+
*
|
|
17
|
+
* - `createSerializer` — an in-process (in-realm) promise chain per key. This
|
|
18
|
+
* is what makes concurrency INSIDE one process correct, and it is the only
|
|
19
|
+
* mechanism that can, since a file lock cannot exclude its own holder.
|
|
20
|
+
* - `withExclusiveLock` — a lock FILE, which is the only thing a second
|
|
21
|
+
* process/realm can see. Injected I/O (`ExclusiveLockIO`) so the same
|
|
22
|
+
* waiting/stale-breaking policy runs over `node:fs` and over a
|
|
23
|
+
* `StorageBackend` without either being reimplemented.
|
|
24
|
+
*
|
|
25
|
+
* This module is deliberately a helper, not a system: no ownership of when a
|
|
26
|
+
* ledger is written, no retries of the caller's work, no state beyond the map a
|
|
27
|
+
* `createSerializer` call hands back.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/** File operations `withExclusiveLock` needs. One lock path per instance. */
|
|
31
|
+
export interface ExclusiveLockIO {
|
|
32
|
+
/** Create the lock holding `content` iff absent. `false` when already held. */
|
|
33
|
+
createIfAbsent(content: string): Promise<boolean>;
|
|
34
|
+
/** The held lock's content, or `null` if it has since vanished. */
|
|
35
|
+
read(): Promise<string | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Delete the lock ONLY while it still holds `expected`. Must tolerate an
|
|
38
|
+
* already-absent lock, and must leave a lock holding anything else alone.
|
|
39
|
+
*
|
|
40
|
+
* There is deliberately no unconditional delete: every deletion in this
|
|
41
|
+
* module is either "release the lock I took" or "break the corpse I judged
|
|
42
|
+
* stale", and both name the exact content they mean. A caller that could
|
|
43
|
+
* delete whatever is there deletes ANOTHER writer's live lock whenever its
|
|
44
|
+
* own view is one step out of date — which is how two writers used to end up
|
|
45
|
+
* inside the critical section at once.
|
|
46
|
+
*
|
|
47
|
+
* The compare and the delete must be ATOMIC WITH RESPECT TO EACH OTHER, and
|
|
48
|
+
* that requirement is on the implementer, not on this module. A backend that
|
|
49
|
+
* reads, compares, then deletes as separate steps reintroduces the same
|
|
50
|
+
* defect one level down: two waiters both compare against the corpse, the
|
|
51
|
+
* first deletes it, acquires and enters, and the second's delete — already
|
|
52
|
+
* past its comparison — removes the winner's fresh lock and lets it in behind
|
|
53
|
+
* it. The two shipped backends each pay for this: the browser one runs inside
|
|
54
|
+
* the `navigator.locks` name `writeIfAbsent` takes, and the `node:fs` one has
|
|
55
|
+
* no atomic compare-and-delete at all and uses `removeIfHeldByTakeover`.
|
|
56
|
+
*/
|
|
57
|
+
removeIfHeldBy(expected: string): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The atomic single steps a takeover-based compare-and-delete needs. Each
|
|
62
|
+
* instance belongs to ONE attempt: the aside path is chosen by the caller and
|
|
63
|
+
* unique per attempt, so two concurrent attempts can never collide on it.
|
|
64
|
+
*
|
|
65
|
+
* On `node:fs` these are `rename`, `readFile`, `rm` and `writeFile` with the
|
|
66
|
+
* `wx` flag — every one a single syscall, which is the whole reason the
|
|
67
|
+
* algorithm below can be reasoned about at all.
|
|
68
|
+
*/
|
|
69
|
+
export interface LockTakeoverOps {
|
|
70
|
+
/**
|
|
71
|
+
* Atomically move the lock to this attempt's aside path. `false` when the
|
|
72
|
+
* lock was not there — which, when several attempts race, is how every
|
|
73
|
+
* attempt but one finds out that it lost.
|
|
74
|
+
*/
|
|
75
|
+
moveAside(): Promise<boolean>;
|
|
76
|
+
/** Content of the moved-aside lock; `null` if it is somehow not there. */
|
|
77
|
+
readAside(): Promise<string | null>;
|
|
78
|
+
deleteAside(): Promise<void>;
|
|
79
|
+
/** Put `content` back at the lock path, ONLY while it is still absent. */
|
|
80
|
+
restoreIfAbsent(content: string): Promise<boolean>;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* `removeIfHeldBy` for a filesystem that has no atomic compare-and-delete:
|
|
85
|
+
* SEIZE the lock with one atomic move, and only then compare.
|
|
86
|
+
*
|
|
87
|
+
* What this buys, and it is the entire point: for a given lock, AT MOST ONE
|
|
88
|
+
* attempt can move it aside. Every other racer's `moveAside` reports `false`
|
|
89
|
+
* and deletes nothing, so it loops, re-reads, and sees the winner's fresh
|
|
90
|
+
* stamp. Read-then-delete could not offer this — its comparison is a snapshot,
|
|
91
|
+
* and a snapshot is stale by the time the delete runs.
|
|
92
|
+
*
|
|
93
|
+
* If the seized content is NOT the content this attempt judged, this attempt had
|
|
94
|
+
* no business taking it: put it straight back, then drop the aside copy.
|
|
95
|
+
*
|
|
96
|
+
* RESIDUAL — stated precisely, because it is not zero. Between the move and the
|
|
97
|
+
* restore, the lock path is briefly absent. A writer whose `createIfAbsent`
|
|
98
|
+
* lands in exactly that gap acquires while the lock's real holder is still
|
|
99
|
+
* inside its critical section. Reaching it takes two coincidences: the content
|
|
100
|
+
* must change between the caller's read and this move (the holder of a stamp
|
|
101
|
+
* older than `staleAfterMs` releasing, and a successor acquiring, inside that
|
|
102
|
+
* window), AND a third writer's create must land inside the restore window.
|
|
103
|
+
* POSIX offers no primitive that closes it — there is no atomic
|
|
104
|
+
* compare-and-delete — and closing it would take a lease/heartbeat protocol
|
|
105
|
+
* with a "your lock was compromised" callback, which this helper deliberately
|
|
106
|
+
* is not.
|
|
107
|
+
*/
|
|
108
|
+
export async function removeIfHeldByTakeover(
|
|
109
|
+
ops: LockTakeoverOps,
|
|
110
|
+
expected: string,
|
|
111
|
+
): Promise<void> {
|
|
112
|
+
if (!(await ops.moveAside())) return;
|
|
113
|
+
const seized = await ops.readAside();
|
|
114
|
+
if (seized !== null && seized !== expected) await ops.restoreIfAbsent(seized);
|
|
115
|
+
await ops.deleteAside();
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export interface ExclusiveLockOptions {
|
|
119
|
+
/**
|
|
120
|
+
* How long a lock may be held before another writer BREAKS it.
|
|
121
|
+
*
|
|
122
|
+
* Breaking, rather than failing, is deliberate: the holder of a lock file is
|
|
123
|
+
* usually a process that has since died (Ctrl-C in the middle of
|
|
124
|
+
* `asset-packs:sync`, a closed tab), and a provenance record must not be
|
|
125
|
+
* refused forever because of a corpse. A real holder finishes in single-digit
|
|
126
|
+
* milliseconds, so this is orders of magnitude above the honest wait — and it
|
|
127
|
+
* is also the loop bound, so waiting can never deadlock.
|
|
128
|
+
*/
|
|
129
|
+
readonly staleAfterMs?: number;
|
|
130
|
+
/** Poll interval while a live lock is held. */
|
|
131
|
+
readonly retryDelayMs?: number;
|
|
132
|
+
/** Recorded in the lock so a human can see who holds it. */
|
|
133
|
+
readonly owner?: string;
|
|
134
|
+
readonly now?: () => number;
|
|
135
|
+
readonly sleep?: (ms: number) => Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* The per-ATTEMPT unique part of the stamp. Injectable so a test can name the
|
|
138
|
+
* attempts it schedules; never for production use.
|
|
139
|
+
*
|
|
140
|
+
* It is load-bearing rather than cosmetic: `removeIfHeldBy` can only tell "my
|
|
141
|
+
* lock" from "someone else's lock" if no two attempts can ever write the same
|
|
142
|
+
* stamp, and `{at, owner}` alone repeats whenever two writers with the same
|
|
143
|
+
* owner name land in the same millisecond.
|
|
144
|
+
*/
|
|
145
|
+
readonly token?: () => string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const DEFAULT_STALE_AFTER_MS = 10_000;
|
|
149
|
+
const DEFAULT_RETRY_DELAY_MS = 15;
|
|
150
|
+
|
|
151
|
+
/** Same guarded form as `../storage/index.ts` — `crypto` is absent in a
|
|
152
|
+
* non-secure browser context, and a missing token must not fail a write. */
|
|
153
|
+
function defaultToken(): string {
|
|
154
|
+
return globalThis.crypto?.randomUUID?.() ?? `${Date.now()}-${Math.random()}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/** Run `work` while holding an exclusive on-disk lock, always releasing it. */
|
|
158
|
+
export async function withExclusiveLock<T>(
|
|
159
|
+
io: ExclusiveLockIO,
|
|
160
|
+
work: () => Promise<T>,
|
|
161
|
+
options: ExclusiveLockOptions = {},
|
|
162
|
+
): Promise<T> {
|
|
163
|
+
const staleAfterMs = options.staleAfterMs ?? DEFAULT_STALE_AFTER_MS;
|
|
164
|
+
const retryDelayMs = options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS;
|
|
165
|
+
const now = options.now ?? Date.now;
|
|
166
|
+
const sleep =
|
|
167
|
+
options.sleep ?? ((ms: number) => new Promise<void>((resolve) => setTimeout(resolve, ms)));
|
|
168
|
+
const token = options.token ?? defaultToken;
|
|
169
|
+
|
|
170
|
+
for (;;) {
|
|
171
|
+
const stamp = JSON.stringify({ at: now(), owner: options.owner ?? 'unknown', token: token() });
|
|
172
|
+
if (await io.createIfAbsent(stamp)) {
|
|
173
|
+
try {
|
|
174
|
+
return await work();
|
|
175
|
+
} finally {
|
|
176
|
+
// Release only OUR lock: if a waiter judged it stale and its successor
|
|
177
|
+
// has already taken the lock, `stamp` is no longer the content and this
|
|
178
|
+
// is a no-op. An unconditional delete here would hand the successor's
|
|
179
|
+
// lock to whoever came next.
|
|
180
|
+
await io.removeIfHeldBy(stamp);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
const held = await io.read();
|
|
184
|
+
// Gone between the failed create and this read — race the create again.
|
|
185
|
+
if (held === null) continue;
|
|
186
|
+
if (now() - lockHeldSince(held) > staleAfterMs) {
|
|
187
|
+
// Break the exact corpse we judged, not "whatever is there now" — an
|
|
188
|
+
// unconditional delete here removes the lock of whoever broke this same
|
|
189
|
+
// corpse a step ahead of us, and lets us walk in behind them.
|
|
190
|
+
//
|
|
191
|
+
// `held` is a SNAPSHOT: by the time the io acts on it, another waiter may
|
|
192
|
+
// have broken this corpse and acquired. That is why `removeIfHeldBy` is
|
|
193
|
+
// required to compare and delete atomically (see its doc comment) rather
|
|
194
|
+
// than being handed a "delete if this is still there" hint it can act on
|
|
195
|
+
// late — the atomicity is what makes at most one waiter break one corpse.
|
|
196
|
+
// The entrant is then decided only by `createIfAbsent`, and the loser of
|
|
197
|
+
// that race loops, re-reads, and sees the winner's fresh stamp.
|
|
198
|
+
await io.removeIfHeldBy(held);
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
await sleep(retryDelayMs);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* When the holder took the lock. An unreadable stamp reports epoch 0, i.e.
|
|
207
|
+
* immediately stale: a lock whose age cannot be established cannot be waited
|
|
208
|
+
* out honestly, and refusing to write provenance because of an unparseable
|
|
209
|
+
* scratch file would be the worse failure.
|
|
210
|
+
*/
|
|
211
|
+
function lockHeldSince(content: string): number {
|
|
212
|
+
try {
|
|
213
|
+
const parsed = JSON.parse(content) as { at?: unknown };
|
|
214
|
+
return typeof parsed.at === 'number' ? parsed.at : 0;
|
|
215
|
+
} catch {
|
|
216
|
+
return 0;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* A per-key promise chain: `serialize(key, work)` starts `work` only after
|
|
222
|
+
* every earlier `work` for that key has settled (rejections included — one
|
|
223
|
+
* failed write must not wedge the queue).
|
|
224
|
+
*
|
|
225
|
+
* Each call returns its OWN map, so two independent callers can never collide
|
|
226
|
+
* on a key that happens to spell the same.
|
|
227
|
+
*/
|
|
228
|
+
export function createSerializer(): <T>(key: string, work: () => Promise<T>) => Promise<T> {
|
|
229
|
+
const tails = new Map<string, Promise<unknown>>();
|
|
230
|
+
return <T>(key: string, work: () => Promise<T>): Promise<T> => {
|
|
231
|
+
const previous = tails.get(key) ?? Promise.resolve();
|
|
232
|
+
const result = previous.then(work, work);
|
|
233
|
+
// Swallow only on the CHAIN copy — the returned promise still rejects.
|
|
234
|
+
const tail = result.then(
|
|
235
|
+
() => undefined,
|
|
236
|
+
() => undefined,
|
|
237
|
+
);
|
|
238
|
+
tails.set(key, tail);
|
|
239
|
+
void tail.then(() => {
|
|
240
|
+
if (tails.get(key) === tail) tails.delete(key);
|
|
241
|
+
});
|
|
242
|
+
return result;
|
|
243
|
+
};
|
|
244
|
+
}
|