@pascal-app/core 0.9.1 → 1.0.0-beta.1
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/README.md +17 -10
- package/dist/events/bus.d.ts +49 -2
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/hooks/scene-registry/item-clip-registry.d.ts +18 -0
- package/dist/hooks/scene-registry/item-clip-registry.d.ts.map +1 -0
- package/dist/hooks/scene-registry/item-clip-registry.js +10 -0
- package/dist/hooks/scene-registry/scene-registry.d.ts +8 -1
- package/dist/hooks/scene-registry/scene-registry.d.ts.map +1 -1
- package/dist/hooks/scene-registry/scene-registry.js +27 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +17 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +61 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +135 -28
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +427 -271
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +46 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +208 -9
- package/dist/hooks/spatial-grid/support-host-id.d.ts +3 -0
- package/dist/hooks/spatial-grid/support-host-id.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/support-host-id.js +2 -0
- package/dist/hooks/spatial-grid/support-host-patch.d.ts +51 -0
- package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/support-host-patch.js +164 -0
- package/dist/index.d.ts +33 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +32 -10
- package/dist/lib/level-name.d.ts +4 -0
- package/dist/lib/level-name.d.ts.map +1 -0
- package/dist/lib/level-name.js +10 -0
- package/dist/lib/measurement-geometry.d.ts +23 -0
- package/dist/lib/measurement-geometry.d.ts.map +1 -0
- package/dist/lib/measurement-geometry.js +249 -0
- package/dist/lib/polygon-geometry.d.ts +0 -1
- package/dist/lib/polygon-geometry.d.ts.map +1 -1
- package/dist/lib/polygon-geometry.js +0 -18
- package/dist/lib/selection-proxy.d.ts +4 -0
- package/dist/lib/selection-proxy.d.ts.map +1 -0
- package/dist/lib/selection-proxy.js +12 -0
- package/dist/lib/slab-polygon.d.ts +31 -2
- package/dist/lib/slab-polygon.d.ts.map +1 -1
- package/dist/lib/slab-polygon.js +557 -31
- package/dist/lib/slots.d.ts +14 -0
- package/dist/lib/slots.d.ts.map +1 -0
- package/dist/lib/slots.js +26 -0
- package/dist/lib/space-detection.d.ts +40 -6
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +574 -192
- package/dist/lib/terrain-brush.d.ts +163 -0
- package/dist/lib/terrain-brush.d.ts.map +1 -0
- package/dist/lib/terrain-brush.js +359 -0
- package/dist/lib/terrain-codec.d.ts +51 -0
- package/dist/lib/terrain-codec.d.ts.map +1 -0
- package/dist/lib/terrain-codec.js +167 -0
- package/dist/lib/terrain-field.d.ts +150 -0
- package/dist/lib/terrain-field.d.ts.map +1 -0
- package/dist/lib/terrain-field.js +248 -0
- package/dist/lib/terrain-raycast.d.ts +44 -0
- package/dist/lib/terrain-raycast.d.ts.map +1 -0
- package/dist/lib/terrain-raycast.js +188 -0
- package/dist/lib/terrain-source.d.ts +60 -0
- package/dist/lib/terrain-source.d.ts.map +1 -0
- package/dist/lib/terrain-source.js +90 -0
- package/dist/lib/terrain-support.d.ts +60 -0
- package/dist/lib/terrain-support.d.ts.map +1 -0
- package/dist/lib/terrain-support.js +150 -0
- package/dist/lib/wall-distance.d.ts +60 -0
- package/dist/lib/wall-distance.d.ts.map +1 -0
- package/dist/lib/wall-distance.js +85 -0
- package/dist/lib/zone-quantities.d.ts +21 -0
- package/dist/lib/zone-quantities.d.ts.map +1 -0
- package/dist/lib/zone-quantities.js +428 -0
- package/dist/material-library.d.ts +28 -1
- package/dist/material-library.d.ts.map +1 -1
- package/dist/material-library.js +2233 -441
- package/dist/registry/handles.d.ts +91 -3
- package/dist/registry/handles.d.ts.map +1 -1
- package/dist/registry/index.d.ts +3 -3
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +1 -1
- package/dist/registry/registry.d.ts +46 -3
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +82 -1
- package/dist/registry/subtree.d.ts.map +1 -1
- package/dist/registry/subtree.js +8 -1
- package/dist/registry/types.d.ts +781 -39
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/schema/index.d.ts +27 -8
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +23 -6
- package/dist/schema/material.d.ts +3 -2
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +7 -5
- package/dist/schema/nodes/box-vent.d.ts +2 -2
- package/dist/schema/nodes/cabinet.d.ts +536 -0
- package/dist/schema/nodes/cabinet.d.ts.map +1 -0
- package/dist/schema/nodes/cabinet.js +139 -0
- package/dist/schema/nodes/ceiling.d.ts +4 -3
- package/dist/schema/nodes/ceiling.d.ts.map +1 -1
- package/dist/schema/nodes/ceiling.js +11 -1
- package/dist/schema/nodes/chimney.d.ts +4 -4
- package/dist/schema/nodes/column.d.ts +4 -2
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +5 -0
- package/dist/schema/nodes/construction-dimension.d.ts +195 -0
- package/dist/schema/nodes/construction-dimension.d.ts.map +1 -0
- package/dist/schema/nodes/construction-dimension.js +151 -0
- package/dist/schema/nodes/cupola.d.ts +2 -2
- package/dist/schema/nodes/door.d.ts +42 -5
- package/dist/schema/nodes/door.d.ts.map +1 -1
- package/dist/schema/nodes/door.js +32 -0
- package/dist/schema/nodes/dormer.d.ts +8 -8
- package/dist/schema/nodes/dormer.js +1 -1
- package/dist/schema/nodes/downspout.d.ts +2 -2
- package/dist/schema/nodes/duct-fitting.d.ts +91 -0
- package/dist/schema/nodes/duct-fitting.d.ts.map +1 -0
- package/dist/schema/nodes/duct-fitting.js +92 -0
- package/dist/schema/nodes/duct-segment.d.ts +61 -0
- package/dist/schema/nodes/duct-segment.d.ts.map +1 -0
- package/dist/schema/nodes/duct-segment.js +73 -0
- package/dist/schema/nodes/duct-terminal.d.ts +58 -0
- package/dist/schema/nodes/duct-terminal.d.ts.map +1 -0
- package/dist/schema/nodes/duct-terminal.js +53 -0
- package/dist/schema/nodes/elevator.d.ts +3 -2
- package/dist/schema/nodes/elevator.d.ts.map +1 -1
- package/dist/schema/nodes/elevator.js +3 -0
- package/dist/schema/nodes/eyebrow-vent.d.ts +2 -2
- package/dist/schema/nodes/fence.d.ts +20 -2
- package/dist/schema/nodes/fence.d.ts.map +1 -1
- package/dist/schema/nodes/fence.js +33 -2
- package/dist/schema/nodes/gutter.d.ts +2 -2
- package/dist/schema/nodes/hvac-equipment.d.ts +64 -0
- package/dist/schema/nodes/hvac-equipment.d.ts.map +1 -0
- package/dist/schema/nodes/hvac-equipment.js +57 -0
- package/dist/schema/nodes/item.d.ts +9 -0
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +24 -0
- package/dist/schema/nodes/level.d.ts +2 -1
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +12 -31
- package/dist/schema/nodes/lineset.d.ts +42 -0
- package/dist/schema/nodes/lineset.d.ts.map +1 -0
- package/dist/schema/nodes/lineset.js +38 -0
- package/dist/schema/nodes/liquid-line.d.ts +34 -0
- package/dist/schema/nodes/liquid-line.d.ts.map +1 -0
- package/dist/schema/nodes/liquid-line.js +24 -0
- package/dist/schema/nodes/measurement.d.ts +306 -0
- package/dist/schema/nodes/measurement.d.ts.map +1 -0
- package/dist/schema/nodes/measurement.js +87 -0
- package/dist/schema/nodes/pipe-fitting.d.ts +56 -0
- package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-fitting.js +45 -0
- package/dist/schema/nodes/pipe-segment.d.ts +48 -0
- package/dist/schema/nodes/pipe-segment.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-segment.js +36 -0
- package/dist/schema/nodes/pipe-trap.d.ts +43 -0
- package/dist/schema/nodes/pipe-trap.d.ts.map +1 -0
- package/dist/schema/nodes/pipe-trap.js +36 -0
- package/dist/schema/nodes/ridge-vent.d.ts +18 -3
- package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
- package/dist/schema/nodes/ridge-vent.js +221 -3
- package/dist/schema/nodes/roof-segment-shape.d.ts +90 -0
- package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-shape.js +318 -0
- package/dist/schema/nodes/roof-segment-walls.d.ts +101 -0
- package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -0
- package/dist/schema/nodes/roof-segment-walls.js +330 -0
- package/dist/schema/nodes/roof-segment.d.ts +84 -8
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +290 -5
- package/dist/schema/nodes/roof.d.ts +8 -8
- package/dist/schema/nodes/shelf.d.ts +4 -2
- package/dist/schema/nodes/shelf.d.ts.map +1 -1
- package/dist/schema/nodes/shelf.js +8 -0
- package/dist/schema/nodes/site.d.ts +9 -0
- package/dist/schema/nodes/site.d.ts.map +1 -1
- package/dist/schema/nodes/site.js +8 -6
- package/dist/schema/nodes/skylight.d.ts +10 -10
- package/dist/schema/nodes/slab.d.ts +8 -2
- package/dist/schema/nodes/slab.d.ts.map +1 -1
- package/dist/schema/nodes/slab.js +18 -2
- package/dist/schema/nodes/solar-panel.d.ts +4 -4
- package/dist/schema/nodes/spawn.d.ts +1 -0
- package/dist/schema/nodes/spawn.d.ts.map +1 -1
- package/dist/schema/nodes/spawn.js +2 -0
- package/dist/schema/nodes/stair-segment.d.ts +4 -4
- package/dist/schema/nodes/stair.d.ts +16 -13
- package/dist/schema/nodes/stair.d.ts.map +1 -1
- package/dist/schema/nodes/stair.js +11 -1
- package/dist/schema/nodes/structural-grid.d.ts +27 -0
- package/dist/schema/nodes/structural-grid.d.ts.map +1 -0
- package/dist/schema/nodes/structural-grid.js +17 -0
- package/dist/schema/nodes/turbine-vent.d.ts +2 -2
- package/dist/schema/nodes/wall.d.ts +248 -6
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +266 -0
- package/dist/schema/nodes/window.d.ts +40 -3
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +30 -0
- package/dist/schema/nodes/zone.d.ts +22 -0
- package/dist/schema/nodes/zone.d.ts.map +1 -1
- package/dist/schema/nodes/zone.js +21 -0
- package/dist/schema/scene-material.d.ts +41 -0
- package/dist/schema/scene-material.d.ts.map +1 -0
- package/dist/schema/scene-material.js +9 -0
- package/dist/schema/terrain.d.ts +28 -0
- package/dist/schema/terrain.d.ts.map +1 -0
- package/dist/schema/terrain.js +30 -0
- package/dist/schema/types.d.ts +1300 -97
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +27 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts +80 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.d.ts.map +1 -0
- package/dist/services/__fixtures__/wall-plane-top-boundary-repro.js +89 -0
- package/dist/services/alignment-anchors.d.ts.map +1 -1
- package/dist/services/alignment-anchors.js +30 -1
- package/dist/services/alignment.d.ts +5 -0
- package/dist/services/alignment.d.ts.map +1 -1
- package/dist/services/alignment.js +2 -0
- package/dist/services/hosting.d.ts +8 -0
- package/dist/services/hosting.d.ts.map +1 -1
- package/dist/services/hosting.js +13 -4
- package/dist/services/index.d.ts +9 -2
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +9 -2
- package/dist/services/level-height.d.ts +27 -0
- package/dist/services/level-height.d.ts.map +1 -0
- package/dist/services/level-height.js +94 -0
- package/dist/services/opening-guides.d.ts +141 -0
- package/dist/services/opening-guides.d.ts.map +1 -0
- package/dist/services/opening-guides.js +267 -0
- package/dist/services/port-connectivity.d.ts +115 -0
- package/dist/services/port-connectivity.d.ts.map +1 -0
- package/dist/services/port-connectivity.js +300 -0
- package/dist/services/riser-diagram.d.ts +40 -0
- package/dist/services/riser-diagram.d.ts.map +1 -0
- package/dist/services/riser-diagram.js +110 -0
- package/dist/services/snap.d.ts +9 -1
- package/dist/services/snap.d.ts.map +1 -1
- package/dist/services/snap.js +21 -1
- package/dist/services/storey.d.ts +103 -0
- package/dist/services/storey.d.ts.map +1 -0
- package/dist/services/storey.js +296 -0
- package/dist/services/system-graph.d.ts +30 -0
- package/dist/services/system-graph.d.ts.map +1 -0
- package/dist/services/system-graph.js +164 -0
- package/dist/services/validate-dwv.d.ts +32 -0
- package/dist/services/validate-dwv.d.ts.map +1 -0
- package/dist/services/validate-dwv.js +118 -0
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +141 -4
- package/dist/store/history-control.d.ts +31 -0
- package/dist/store/history-control.d.ts.map +1 -1
- package/dist/store/history-control.js +130 -0
- package/dist/store/use-live-terrain.d.ts +65 -0
- package/dist/store/use-live-terrain.d.ts.map +1 -0
- package/dist/store/use-live-terrain.js +31 -0
- package/dist/store/use-live-transforms.d.ts +8 -0
- package/dist/store/use-live-transforms.d.ts.map +1 -1
- package/dist/store/use-scene.d.ts +47 -3
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +992 -55
- package/dist/systems/elevator/elevator-opening-system.d.ts +1 -0
- package/dist/systems/elevator/elevator-opening-system.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-opening-system.js +27 -21
- package/dist/systems/elevator/elevator-service.d.ts +0 -2
- package/dist/systems/elevator/elevator-service.d.ts.map +1 -1
- package/dist/systems/elevator/elevator-service.js +2 -24
- package/dist/systems/fence/fence-centerline.d.ts +12 -0
- package/dist/systems/fence/fence-centerline.d.ts.map +1 -0
- package/dist/systems/fence/fence-centerline.js +37 -0
- package/dist/systems/fence/fence-spline.d.ts +39 -0
- package/dist/systems/fence/fence-spline.d.ts.map +1 -0
- package/dist/systems/fence/fence-spline.js +196 -0
- package/dist/systems/slab/slab-placement.d.ts +11 -0
- package/dist/systems/slab/slab-placement.d.ts.map +1 -0
- package/dist/systems/slab/slab-placement.js +14 -0
- package/dist/systems/slab/slab-support.d.ts +137 -0
- package/dist/systems/slab/slab-support.d.ts.map +1 -0
- package/dist/systems/slab/slab-support.js +557 -0
- package/dist/systems/stair/stair-footprint.d.ts.map +1 -1
- package/dist/systems/stair/stair-footprint.js +21 -11
- package/dist/systems/stair/stair-opening-preview.d.ts +1300 -505
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-sync.js +19 -33
- package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-system.js +32 -4
- package/dist/systems/stair/stair-rise.d.ts +22 -0
- package/dist/systems/stair/stair-rise.d.ts.map +1 -0
- package/dist/systems/stair/stair-rise.js +79 -0
- package/dist/systems/wall/wall-curve.d.ts +10 -0
- package/dist/systems/wall/wall-curve.d.ts.map +1 -1
- package/dist/systems/wall/wall-curve.js +1 -1
- package/dist/systems/wall/wall-mitering.d.ts.map +1 -1
- package/dist/systems/wall/wall-mitering.js +44 -8
- package/dist/systems/wall/wall-top.d.ts +40 -0
- package/dist/systems/wall/wall-top.d.ts.map +1 -0
- package/dist/systems/wall/wall-top.js +46 -0
- package/dist/utils/clone-scene-graph.d.ts +1 -0
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +56 -5
- package/dist/utils/heal-scene-graph.d.ts +18 -0
- package/dist/utils/heal-scene-graph.d.ts.map +1 -0
- package/dist/utils/heal-scene-graph.js +106 -0
- package/dist/validation/validate-build-json.d.ts +3 -0
- package/dist/validation/validate-build-json.d.ts.map +1 -1
- package/dist/validation/validate-build-json.js +90 -5
- package/package.json +4 -4
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts +0 -2
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.d.ts.map +0 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.test.js +0 -273
- package/dist/lib/space-detection-pause.test.d.ts +0 -2
- package/dist/lib/space-detection-pause.test.d.ts.map +0 -1
- package/dist/lib/space-detection-pause.test.js +0 -42
- package/dist/lib/space-detection.test.d.ts +0 -2
- package/dist/lib/space-detection.test.d.ts.map +0 -1
- package/dist/lib/space-detection.test.js +0 -77
- package/dist/registry/registry.test.d.ts +0 -2
- package/dist/registry/registry.test.d.ts.map +0 -1
- package/dist/registry/registry.test.js +0 -183
- package/dist/registry/relations-resolver.test.d.ts +0 -2
- package/dist/registry/relations-resolver.test.d.ts.map +0 -1
- package/dist/registry/relations-resolver.test.js +0 -183
- package/dist/registry/scene-api.test.d.ts +0 -2
- package/dist/registry/scene-api.test.d.ts.map +0 -1
- package/dist/registry/scene-api.test.js +0 -183
- package/dist/registry/subtree.test.d.ts +0 -2
- package/dist/registry/subtree.test.d.ts.map +0 -1
- package/dist/registry/subtree.test.js +0 -133
- package/dist/schema/asset-url.test.d.ts +0 -2
- package/dist/schema/asset-url.test.d.ts.map +0 -1
- package/dist/schema/asset-url.test.js +0 -134
- package/dist/services/alignment-anchors.test.d.ts +0 -2
- package/dist/services/alignment-anchors.test.d.ts.map +0 -1
- package/dist/services/alignment-anchors.test.js +0 -383
- package/dist/services/alignment.test.d.ts +0 -2
- package/dist/services/alignment.test.d.ts.map +0 -1
- package/dist/services/alignment.test.js +0 -92
- package/dist/services/drag-session.test.d.ts +0 -2
- package/dist/services/drag-session.test.d.ts.map +0 -1
- package/dist/services/drag-session.test.js +0 -219
- package/dist/services/hosting.test.d.ts +0 -2
- package/dist/services/hosting.test.d.ts.map +0 -1
- package/dist/services/hosting.test.js +0 -199
- package/dist/services/movement.test.d.ts +0 -2
- package/dist/services/movement.test.d.ts.map +0 -1
- package/dist/services/movement.test.js +0 -133
- package/dist/services/single-undo-dance.test.d.ts +0 -2
- package/dist/services/single-undo-dance.test.d.ts.map +0 -1
- package/dist/services/single-undo-dance.test.js +0 -210
- package/dist/services/snap.test.d.ts +0 -2
- package/dist/services/snap.test.d.ts.map +0 -1
- package/dist/services/snap.test.js +0 -95
- package/dist/store/actions/node-mutation-sanitize.test.d.ts +0 -2
- package/dist/store/actions/node-mutation-sanitize.test.d.ts.map +0 -1
- package/dist/store/actions/node-mutation-sanitize.test.js +0 -147
- package/dist/store/actions/reparent.test.d.ts +0 -2
- package/dist/store/actions/reparent.test.d.ts.map +0 -1
- package/dist/store/actions/reparent.test.js +0 -212
- package/dist/store/use-scene-elevator-migration.test.d.ts +0 -2
- package/dist/store/use-scene-elevator-migration.test.d.ts.map +0 -1
- package/dist/store/use-scene-elevator-migration.test.js +0 -109
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts +0 -2
- package/dist/systems/elevator/elevator-opening-sync.test.d.ts.map +0 -1
- package/dist/systems/elevator/elevator-opening-sync.test.js +0 -146
- package/dist/systems/elevator/elevator-runtime.test.d.ts +0 -2
- package/dist/systems/elevator/elevator-runtime.test.d.ts.map +0 -1
- package/dist/systems/elevator/elevator-runtime.test.js +0 -64
- package/dist/systems/stair/stair-opening-preview.test.d.ts +0 -2
- package/dist/systems/stair/stair-opening-preview.test.d.ts.map +0 -1
- package/dist/systems/stair/stair-opening-preview.test.js +0 -80
- package/dist/systems/stair/stair-opening-sync.test.d.ts +0 -2
- package/dist/systems/stair/stair-opening-sync.test.d.ts.map +0 -1
- package/dist/systems/stair/stair-opening-sync.test.js +0 -446
- package/dist/utils/clone-scene-graph.test.d.ts +0 -2
- package/dist/utils/clone-scene-graph.test.d.ts.map +0 -1
- package/dist/utils/clone-scene-graph.test.js +0 -59
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { GROUND_SUPPORT_ID } from '../hooks/spatial-grid/floor-placed-elevation';
|
|
2
|
+
import { remapConstructionDimensionReferences, remapMeasurementReferences, } from '../lib/measurement-geometry';
|
|
1
3
|
import { generateId } from '../schema/base';
|
|
2
4
|
/**
|
|
3
5
|
* Extracts the type prefix from a node ID (e.g., "wall_abc123" -> "wall")
|
|
@@ -16,7 +18,7 @@ function extractIdPrefix(id) {
|
|
|
16
18
|
* - Multi-scene in-memory scenarios
|
|
17
19
|
*/
|
|
18
20
|
export function cloneSceneGraph(sceneGraph) {
|
|
19
|
-
const { nodes, rootNodeIds, collections } = sceneGraph;
|
|
21
|
+
const { nodes, rootNodeIds, collections, installedPlugins } = sceneGraph;
|
|
20
22
|
// Build ID mapping: old ID -> new ID
|
|
21
23
|
const idMap = new Map();
|
|
22
24
|
// Pass 1: Generate new IDs for all nodes
|
|
@@ -28,7 +30,7 @@ export function cloneSceneGraph(sceneGraph) {
|
|
|
28
30
|
const clonedNodes = {};
|
|
29
31
|
for (const [oldId, node] of Object.entries(nodes)) {
|
|
30
32
|
const newId = idMap.get(oldId);
|
|
31
|
-
|
|
33
|
+
let clonedNode = structuredClone({ ...node, id: newId });
|
|
32
34
|
// Remap parentId
|
|
33
35
|
if (clonedNode.parentId && typeof clonedNode.parentId === 'string') {
|
|
34
36
|
clonedNode.parentId = (idMap.get(clonedNode.parentId) ?? null);
|
|
@@ -57,6 +59,29 @@ export function cloneSceneGraph(sceneGraph) {
|
|
|
57
59
|
;
|
|
58
60
|
clonedNode.wallId = idMap.get(clonedNode.wallId);
|
|
59
61
|
}
|
|
62
|
+
// Remap roofSegmentId (doors/windows/items hosted on roof wall faces)
|
|
63
|
+
if ('roofSegmentId' in clonedNode && typeof clonedNode.roofSegmentId === 'string') {
|
|
64
|
+
;
|
|
65
|
+
clonedNode.roofSegmentId = idMap.get(clonedNode.roofSegmentId);
|
|
66
|
+
}
|
|
67
|
+
// Remap supportSlabId (persisted slab-support hosts). The 'ground'
|
|
68
|
+
// sentinel is not a node id — keep it as-is.
|
|
69
|
+
if ('supportSlabId' in clonedNode &&
|
|
70
|
+
typeof clonedNode.supportSlabId === 'string' &&
|
|
71
|
+
clonedNode.supportSlabId !== GROUND_SUPPORT_ID) {
|
|
72
|
+
;
|
|
73
|
+
clonedNode.supportSlabId = idMap.get(clonedNode.supportSlabId);
|
|
74
|
+
}
|
|
75
|
+
if ('deckSlabId' in clonedNode && typeof clonedNode.deckSlabId === 'string') {
|
|
76
|
+
;
|
|
77
|
+
clonedNode.deckSlabId = idMap.get(clonedNode.deckSlabId);
|
|
78
|
+
}
|
|
79
|
+
if (clonedNode.type === 'measurement') {
|
|
80
|
+
clonedNode.measurement = remapMeasurementReferences(clonedNode.measurement, idMap);
|
|
81
|
+
}
|
|
82
|
+
if (clonedNode.type === 'construction-dimension') {
|
|
83
|
+
clonedNode = remapConstructionDimensionReferences(clonedNode, idMap);
|
|
84
|
+
}
|
|
60
85
|
clonedNodes[newId] = clonedNode;
|
|
61
86
|
}
|
|
62
87
|
// Remap root node IDs
|
|
@@ -102,6 +127,7 @@ export function cloneSceneGraph(sceneGraph) {
|
|
|
102
127
|
nodes: clonedNodes,
|
|
103
128
|
rootNodeIds: clonedRootNodeIds,
|
|
104
129
|
...(clonedCollections && { collections: clonedCollections }),
|
|
130
|
+
...(installedPlugins && { installedPlugins: [...installedPlugins] }),
|
|
105
131
|
};
|
|
106
132
|
}
|
|
107
133
|
/**
|
|
@@ -119,7 +145,7 @@ export function cloneSceneGraph(sceneGraph) {
|
|
|
119
145
|
*/
|
|
120
146
|
export function cloneLevelSubtree(nodes, levelId) {
|
|
121
147
|
const levelNode = nodes[levelId];
|
|
122
|
-
if (
|
|
148
|
+
if (levelNode?.type !== 'level') {
|
|
123
149
|
throw new Error(`Node "${levelId}" is not a level`);
|
|
124
150
|
}
|
|
125
151
|
// Recursively collect the level node + all descendants via children arrays
|
|
@@ -156,7 +182,7 @@ export function cloneLevelSubtree(nodes, levelId) {
|
|
|
156
182
|
continue;
|
|
157
183
|
const newId = idMap.get(oldId);
|
|
158
184
|
// JSON roundtrip: safely strips functions, Object3D, circular refs, etc.
|
|
159
|
-
|
|
185
|
+
let cloned = JSON.parse(JSON.stringify(node));
|
|
160
186
|
cloned.id = newId;
|
|
161
187
|
// Remap parentId — but only for descendants, not the level node itself
|
|
162
188
|
// (the level's parentId points to the building, which is outside the subtree)
|
|
@@ -185,6 +211,30 @@ export function cloneLevelSubtree(nodes, levelId) {
|
|
|
185
211
|
;
|
|
186
212
|
cloned.wallId = idMap.get(cloned.wallId) ?? cloned.wallId;
|
|
187
213
|
}
|
|
214
|
+
// Remap roofSegmentId (doors/windows/items hosted on roof wall faces)
|
|
215
|
+
if ('roofSegmentId' in cloned && typeof cloned.roofSegmentId === 'string') {
|
|
216
|
+
;
|
|
217
|
+
cloned.roofSegmentId =
|
|
218
|
+
idMap.get(cloned.roofSegmentId) ?? cloned.roofSegmentId;
|
|
219
|
+
}
|
|
220
|
+
// Remap supportSlabId when the host slab is inside the cloned subtree;
|
|
221
|
+
// preserve it otherwise (like wallId, the reference may point outside).
|
|
222
|
+
if ('supportSlabId' in cloned && typeof cloned.supportSlabId === 'string') {
|
|
223
|
+
;
|
|
224
|
+
cloned.supportSlabId =
|
|
225
|
+
idMap.get(cloned.supportSlabId) ?? cloned.supportSlabId;
|
|
226
|
+
}
|
|
227
|
+
if ('deckSlabId' in cloned && typeof cloned.deckSlabId === 'string') {
|
|
228
|
+
;
|
|
229
|
+
cloned.deckSlabId =
|
|
230
|
+
idMap.get(cloned.deckSlabId) ?? cloned.deckSlabId;
|
|
231
|
+
}
|
|
232
|
+
if (cloned.type === 'measurement') {
|
|
233
|
+
cloned.measurement = remapMeasurementReferences(cloned.measurement, idMap);
|
|
234
|
+
}
|
|
235
|
+
if (cloned.type === 'construction-dimension') {
|
|
236
|
+
cloned = remapConstructionDimensionReferences(cloned, idMap);
|
|
237
|
+
}
|
|
188
238
|
clonedNodes.push(cloned);
|
|
189
239
|
}
|
|
190
240
|
return { clonedNodes, newLevelId, idMap };
|
|
@@ -197,7 +247,7 @@ export function forkSceneGraph(sceneGraph, options = {}) {
|
|
|
197
247
|
if (options.preserveScans) {
|
|
198
248
|
return cloneSceneGraph(sceneGraph);
|
|
199
249
|
}
|
|
200
|
-
const { nodes, rootNodeIds, collections } = sceneGraph;
|
|
250
|
+
const { nodes, rootNodeIds, collections, installedPlugins } = sceneGraph;
|
|
201
251
|
// First, identify scan and guide node IDs to exclude (user-uploaded imagery)
|
|
202
252
|
const excludedNodeIds = new Set();
|
|
203
253
|
for (const [nodeId, node] of Object.entries(nodes)) {
|
|
@@ -249,5 +299,6 @@ export function forkSceneGraph(sceneGraph, options = {}) {
|
|
|
249
299
|
nodes: filteredNodes,
|
|
250
300
|
rootNodeIds: filteredRootNodeIds,
|
|
251
301
|
...(filteredCollections && { collections: filteredCollections }),
|
|
302
|
+
...(installedPlugins && { installedPlugins }),
|
|
252
303
|
});
|
|
253
304
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface HealSceneResult {
|
|
2
|
+
nodes: Record<string, unknown>;
|
|
3
|
+
/** Ids of zero-length walls that were dropped. */
|
|
4
|
+
droppedWallIds: string[];
|
|
5
|
+
/** Count of invalid non-string (e.g. null) entries removed from `children` arrays. */
|
|
6
|
+
strippedChildRefs: number;
|
|
7
|
+
/**
|
|
8
|
+
* Count of child references removed because the child's `parentId` points at
|
|
9
|
+
* a different node (stale reparent leftovers), plus same-array duplicates.
|
|
10
|
+
*/
|
|
11
|
+
strippedStaleChildRefs: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Returns a healed copy of a `nodes` map. Pure — does not mutate `input`.
|
|
15
|
+
* Nodes that need no repair are passed through by reference.
|
|
16
|
+
*/
|
|
17
|
+
export declare function healSceneNodes(input: Record<string, unknown>): HealSceneResult;
|
|
18
|
+
//# sourceMappingURL=heal-scene-graph.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heal-scene-graph.d.ts","sourceRoot":"","sources":["../../src/utils/heal-scene-graph.ts"],"names":[],"mappings":"AAqBA,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,kDAAkD;IAClD,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,sFAAsF;IACtF,iBAAiB,EAAE,MAAM,CAAA;IACzB;;;OAGG;IACH,sBAAsB,EAAE,MAAM,CAAA;CAC/B;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CA2E9E"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Repairs scene-graph corruption that pre-dates the source fixes, so existing
|
|
2
|
+
// saved scenes still load. Known kinds of damage:
|
|
3
|
+
//
|
|
4
|
+
// 1. A `children` array containing a non-string entry. The capture wall-merge
|
|
5
|
+
// re-attached a wall-hosted item without minting an id, so `undefined` was
|
|
6
|
+
// pushed into the wall's children — which serializes to `[null]`. The wall
|
|
7
|
+
// schema rejects `null` children, so the whole scene fails to load.
|
|
8
|
+
// 2. A zero-length wall (start === end). It renders nothing, but lingers as a
|
|
9
|
+
// junk node and is a foot-gun for snapping/mitering.
|
|
10
|
+
// 3. A child referenced by a parent it no longer belongs to: the child's
|
|
11
|
+
// `parentId` points at node B while node A's `children` still lists it
|
|
12
|
+
// (stale leftover from a reparent that didn't clean the old parent). The
|
|
13
|
+
// duplicate reference renders the child twice (duplicate React keys in the
|
|
14
|
+
// 2D plan, doubled hosted geometry in 3D). Same-array duplicates are
|
|
15
|
+
// collapsed too.
|
|
16
|
+
//
|
|
17
|
+
// All are also prevented at the source now; this is the load-time safety net
|
|
18
|
+
// for already-saved scenes.
|
|
19
|
+
const ZERO_LENGTH_EPS = 1e-6;
|
|
20
|
+
function isWallLike(node) {
|
|
21
|
+
if (!node || typeof node !== 'object')
|
|
22
|
+
return false;
|
|
23
|
+
const n = node;
|
|
24
|
+
return (n.type === 'wall' &&
|
|
25
|
+
Array.isArray(n.start) &&
|
|
26
|
+
Array.isArray(n.end) &&
|
|
27
|
+
typeof n.start[0] === 'number' &&
|
|
28
|
+
typeof n.start[1] === 'number' &&
|
|
29
|
+
typeof n.end[0] === 'number' &&
|
|
30
|
+
typeof n.end[1] === 'number');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Returns a healed copy of a `nodes` map. Pure — does not mutate `input`.
|
|
34
|
+
* Nodes that need no repair are passed through by reference.
|
|
35
|
+
*/
|
|
36
|
+
export function healSceneNodes(input) {
|
|
37
|
+
const droppedWallIds = [];
|
|
38
|
+
// Pass 1: drop childless zero-length walls. (Only childless ones — a wall
|
|
39
|
+
// carrying a door/window must keep its hosts, degenerate or not.)
|
|
40
|
+
const kept = {};
|
|
41
|
+
for (const [id, node] of Object.entries(input)) {
|
|
42
|
+
if (isWallLike(node)) {
|
|
43
|
+
const children = node.children;
|
|
44
|
+
const childless = !Array.isArray(children) || children.length === 0;
|
|
45
|
+
const dx = node.end[0] - node.start[0];
|
|
46
|
+
const dz = node.end[1] - node.start[1];
|
|
47
|
+
if (childless && Math.hypot(dx, dz) <= ZERO_LENGTH_EPS) {
|
|
48
|
+
droppedWallIds.push(id);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
kept[id] = node;
|
|
53
|
+
}
|
|
54
|
+
const dropped = new Set(droppedWallIds);
|
|
55
|
+
let strippedChildRefs = 0;
|
|
56
|
+
let strippedStaleChildRefs = 0;
|
|
57
|
+
// Pass 2: clean `children` arrays — drop invalid non-string entries (the
|
|
58
|
+
// `[null]` bug), references to walls we just removed, same-array duplicates,
|
|
59
|
+
// and stale references whose child's `parentId` names a different parent.
|
|
60
|
+
// Legacy sites embedded full child objects; keep those for migrateNodes to
|
|
61
|
+
// flatten after healing instead of disconnecting the entire building.
|
|
62
|
+
const nodes = {};
|
|
63
|
+
for (const [id, node] of Object.entries(kept)) {
|
|
64
|
+
const children = node?.children;
|
|
65
|
+
if (Array.isArray(children)) {
|
|
66
|
+
const seen = new Set();
|
|
67
|
+
const cleaned = children.filter((child) => {
|
|
68
|
+
const embeddedSiteChildId = node.type === 'site' &&
|
|
69
|
+
child &&
|
|
70
|
+
typeof child === 'object' &&
|
|
71
|
+
typeof child.id === 'string'
|
|
72
|
+
? child.id
|
|
73
|
+
: null;
|
|
74
|
+
if (embeddedSiteChildId) {
|
|
75
|
+
if (seen.has(embeddedSiteChildId)) {
|
|
76
|
+
strippedStaleChildRefs++;
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
seen.add(embeddedSiteChildId);
|
|
80
|
+
return true;
|
|
81
|
+
}
|
|
82
|
+
if (typeof child !== 'string' || dropped.has(child)) {
|
|
83
|
+
strippedChildRefs++;
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (seen.has(child)) {
|
|
87
|
+
strippedStaleChildRefs++;
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
seen.add(child);
|
|
91
|
+
const childNode = kept[child];
|
|
92
|
+
if (childNode && typeof childNode.parentId === 'string' && childNode.parentId !== id) {
|
|
93
|
+
strippedStaleChildRefs++;
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
return true;
|
|
97
|
+
});
|
|
98
|
+
if (cleaned.length !== children.length) {
|
|
99
|
+
nodes[id] = { ...node, children: cleaned };
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
nodes[id] = node;
|
|
104
|
+
}
|
|
105
|
+
return { nodes, droppedWallIds, strippedChildRefs, strippedStaleChildRefs };
|
|
106
|
+
}
|
|
@@ -9,12 +9,15 @@ export type ValidationIssue = {
|
|
|
9
9
|
export type BuildStats = {
|
|
10
10
|
total: number;
|
|
11
11
|
byType: Partial<Record<AnyNodeType, number>>;
|
|
12
|
+
/** Kinds outside the static schema union but registered at runtime (plugins). */
|
|
13
|
+
pluginTypes: Record<string, number>;
|
|
12
14
|
unknownTypes: Record<string, number>;
|
|
13
15
|
floorAreaM2: number;
|
|
14
16
|
};
|
|
15
17
|
export type ParsedBuildJson = {
|
|
16
18
|
nodes: Record<string, unknown>;
|
|
17
19
|
rootNodeIds: string[];
|
|
20
|
+
installedPlugins?: string[];
|
|
18
21
|
};
|
|
19
22
|
export type SchemaIssue = {
|
|
20
23
|
nodeId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate-build-json.d.ts","sourceRoot":"","sources":["../../src/validation/validate-build-json.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate-build-json.d.ts","sourceRoot":"","sources":["../../src/validation/validate-build-json.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAG3D,MAAM,MAAM,kBAAkB,GAAG,OAAO,GAAG,SAAS,CAAA;AAEpD,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,kBAAkB,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5C,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACpC,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;CAC5B,CAAA;AAED,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,eAAe,GAAG,IAAI,CAAA;IAC9B,KAAK,EAAE,UAAU,CAAA;IACjB,MAAM,EAAE,eAAe,EAAE,CAAA;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAA;IAC3B,YAAY,EAAE,WAAW,EAAE,CAAA;IAC3B,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAA;AA8BD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,uBAAuB,CA8SzE"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { nodeRegistry } from '../registry';
|
|
1
2
|
import { AnyNode } from '../schema/types';
|
|
3
|
+
import { healSceneNodes } from '../utils/heal-scene-graph';
|
|
2
4
|
const KNOWN_TYPES = new Set(AnyNode.options.map((o) => o.shape.type.parse(undefined)));
|
|
3
5
|
function isPlainObject(value) {
|
|
4
6
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
@@ -33,7 +35,13 @@ export function validateBuildJson(input) {
|
|
|
33
35
|
const errors = [];
|
|
34
36
|
const warnings = [];
|
|
35
37
|
const schemaIssues = [];
|
|
36
|
-
const stats = {
|
|
38
|
+
const stats = {
|
|
39
|
+
total: 0,
|
|
40
|
+
byType: {},
|
|
41
|
+
pluginTypes: {},
|
|
42
|
+
unknownTypes: {},
|
|
43
|
+
floorAreaM2: 0,
|
|
44
|
+
};
|
|
37
45
|
if (!isPlainObject(input)) {
|
|
38
46
|
errors.push({
|
|
39
47
|
severity: 'error',
|
|
@@ -52,6 +60,7 @@ export function validateBuildJson(input) {
|
|
|
52
60
|
}
|
|
53
61
|
const nodesRaw = input.nodes;
|
|
54
62
|
const rootNodeIdsRaw = input.rootNodeIds;
|
|
63
|
+
const installedPluginsRaw = input.installedPlugins;
|
|
55
64
|
if (!isPlainObject(nodesRaw)) {
|
|
56
65
|
errors.push({
|
|
57
66
|
severity: 'error',
|
|
@@ -77,8 +86,29 @@ export function validateBuildJson(input) {
|
|
|
77
86
|
schemaIssueCount: 0,
|
|
78
87
|
};
|
|
79
88
|
}
|
|
80
|
-
|
|
89
|
+
// Heal known pre-existing corruption (null children, zero-length walls) up
|
|
90
|
+
// front, so a scene saved before the source fixes still imports instead of
|
|
91
|
+
// hard-failing schema validation. `parsed` below carries the repaired nodes.
|
|
92
|
+
const { nodes, droppedWallIds, strippedChildRefs } = healSceneNodes(nodesRaw);
|
|
81
93
|
const rootNodeIds = rootNodeIdsRaw;
|
|
94
|
+
const installedPlugins = Array.isArray(installedPluginsRaw) &&
|
|
95
|
+
installedPluginsRaw.every((pluginId) => typeof pluginId === 'string')
|
|
96
|
+
? Array.from(new Set(installedPluginsRaw))
|
|
97
|
+
: undefined;
|
|
98
|
+
if (installedPluginsRaw !== undefined && installedPlugins === undefined) {
|
|
99
|
+
warnings.push({
|
|
100
|
+
severity: 'warning',
|
|
101
|
+
code: 'invalid_installed_plugins',
|
|
102
|
+
message: 'Ignored invalid "installedPlugins" — expected an array of plugin IDs.',
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
if (strippedChildRefs > 0 || droppedWallIds.length > 0) {
|
|
106
|
+
warnings.push({
|
|
107
|
+
severity: 'warning',
|
|
108
|
+
code: 'auto_repaired',
|
|
109
|
+
message: `Repaired on import: removed ${strippedChildRefs} invalid child reference${strippedChildRefs === 1 ? '' : 's'} and ${droppedWallIds.length} zero-length wall${droppedWallIds.length === 1 ? '' : 's'}.`,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
82
112
|
if (rootNodeIds.length === 0) {
|
|
83
113
|
errors.push({
|
|
84
114
|
severity: 'error',
|
|
@@ -86,6 +116,33 @@ export function validateBuildJson(input) {
|
|
|
86
116
|
message: '"rootNodeIds" is empty — no entry point into the scene.',
|
|
87
117
|
});
|
|
88
118
|
}
|
|
119
|
+
// Ids of nodes whose type falls outside the static schema union — plugin
|
|
120
|
+
// kinds (`trees:tree`) or genuinely unknown types. The scene store accepts
|
|
121
|
+
// them on load (they already round-trip through the DB fine) and they're
|
|
122
|
+
// surfaced by the unknown-types warning, but a parent's strict `children`
|
|
123
|
+
// id union would hard-fail over them: validate parents against a copy with
|
|
124
|
+
// those ids filtered out. The imported data itself keeps them.
|
|
125
|
+
const nonSchemaNodeIds = new Set();
|
|
126
|
+
for (const [key, value] of Object.entries(nodes)) {
|
|
127
|
+
if (!isPlainObject(value))
|
|
128
|
+
continue;
|
|
129
|
+
const type = typeof value.type === 'string' ? value.type : null;
|
|
130
|
+
if (type && KNOWN_TYPES.has(type))
|
|
131
|
+
continue;
|
|
132
|
+
nonSchemaNodeIds.add(typeof value.id === 'string' ? value.id : key);
|
|
133
|
+
}
|
|
134
|
+
const withoutNonSchemaChildren = (value) => {
|
|
135
|
+
const children = value.children;
|
|
136
|
+
if (!Array.isArray(children))
|
|
137
|
+
return value;
|
|
138
|
+
if (!children.some((child) => typeof child === 'string' && nonSchemaNodeIds.has(child))) {
|
|
139
|
+
return value;
|
|
140
|
+
}
|
|
141
|
+
return {
|
|
142
|
+
...value,
|
|
143
|
+
children: children.filter((child) => !(typeof child === 'string' && nonSchemaNodeIds.has(child))),
|
|
144
|
+
};
|
|
145
|
+
};
|
|
89
146
|
let validRootCount = 0;
|
|
90
147
|
let mismatchedKeyCount = 0;
|
|
91
148
|
let schemaFailureCount = 0;
|
|
@@ -118,7 +175,7 @@ export function validateBuildJson(input) {
|
|
|
118
175
|
if (KNOWN_TYPES.has(type)) {
|
|
119
176
|
const t = type;
|
|
120
177
|
stats.byType[t] = (stats.byType[t] ?? 0) + 1;
|
|
121
|
-
const parseResult = AnyNode.safeParse(value);
|
|
178
|
+
const parseResult = AnyNode.safeParse(withoutNonSchemaChildren(value));
|
|
122
179
|
if (!parseResult.success) {
|
|
123
180
|
schemaFailureCount += 1;
|
|
124
181
|
const issue = parseResult.error.issues[0];
|
|
@@ -145,7 +202,29 @@ export function validateBuildJson(input) {
|
|
|
145
202
|
}
|
|
146
203
|
}
|
|
147
204
|
else {
|
|
148
|
-
|
|
205
|
+
const registered = nodeRegistry.get(type);
|
|
206
|
+
if (registered) {
|
|
207
|
+
// A runtime-registered plugin kind (e.g. `trees:tree`) is a
|
|
208
|
+
// first-class citizen: validate it with its own registered schema
|
|
209
|
+
// instead of flagging it unknown. Files from projects whose plugin
|
|
210
|
+
// is NOT loaded here still fall through to the unknown-types
|
|
211
|
+
// warning below.
|
|
212
|
+
stats.pluginTypes[type] = (stats.pluginTypes[type] ?? 0) + 1;
|
|
213
|
+
const parseResult = registered.schema.safeParse(value);
|
|
214
|
+
if (!parseResult.success) {
|
|
215
|
+
schemaFailureCount += 1;
|
|
216
|
+
const issue = parseResult.error.issues[0];
|
|
217
|
+
schemaIssues.push({
|
|
218
|
+
nodeId: key,
|
|
219
|
+
nodeType: type,
|
|
220
|
+
path: issue ? issue.path.join('.') : '',
|
|
221
|
+
message: issue ? issue.message : 'schema mismatch',
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
stats.unknownTypes[type] = (stats.unknownTypes[type] ?? 0) + 1;
|
|
227
|
+
}
|
|
149
228
|
}
|
|
150
229
|
if (parentId && !(parentId in nodes)) {
|
|
151
230
|
warnings.push({
|
|
@@ -217,7 +296,13 @@ export function validateBuildJson(input) {
|
|
|
217
296
|
const ok = errors.length === 0;
|
|
218
297
|
return {
|
|
219
298
|
ok,
|
|
220
|
-
parsed: ok
|
|
299
|
+
parsed: ok
|
|
300
|
+
? {
|
|
301
|
+
nodes,
|
|
302
|
+
rootNodeIds,
|
|
303
|
+
...(installedPlugins ? { installedPlugins } : {}),
|
|
304
|
+
}
|
|
305
|
+
: null,
|
|
221
306
|
stats,
|
|
222
307
|
errors,
|
|
223
308
|
warnings,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pascal-app/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0-beta.1",
|
|
4
4
|
"description": "Core library for Pascal 3D building editor",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -58,8 +58,8 @@
|
|
|
58
58
|
],
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsc --build",
|
|
61
|
-
"dev": "
|
|
62
|
-
"test": "bun test",
|
|
61
|
+
"dev": "tsgo --build --watch",
|
|
62
|
+
"test": "bun test src",
|
|
63
63
|
"bench:registry": "bun run src/registry/__bench__/relations-resolver.bench.ts",
|
|
64
64
|
"prepublishOnly": "npm run build"
|
|
65
65
|
},
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"@react-three/drei": "^10",
|
|
68
68
|
"@react-three/fiber": "^9",
|
|
69
69
|
"react": "^18 || ^19",
|
|
70
|
-
"three": "^0.
|
|
70
|
+
"three": "^0.185"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"dedent": "^1.7.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"floor-placed-elevation.test.d.ts","sourceRoot":"","sources":["../../../src/hooks/spatial-grid/floor-placed-elevation.test.ts"],"names":[],"mappings":""}
|