@pascal-app/core 1.0.0-beta.5 → 1.0.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/LICENSE +21 -0
- package/README.md +23 -0
- package/dist/capture/index.d.ts +3 -0
- package/dist/capture/index.d.ts.map +1 -0
- package/dist/capture/index.js +2 -0
- package/dist/capture/schema.d.ts +417 -0
- package/dist/capture/schema.d.ts.map +1 -0
- package/dist/capture/schema.js +350 -0
- package/dist/capture/source.d.ts +60 -0
- package/dist/capture/source.d.ts.map +1 -0
- package/dist/capture/source.js +254 -0
- package/dist/events/bus.d.ts +58 -7
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/hidden-wall-pointer-hold.d.ts +28 -0
- package/dist/events/hidden-wall-pointer-hold.d.ts.map +1 -0
- package/dist/events/hidden-wall-pointer-hold.js +37 -0
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts +4 -4
- package/dist/hooks/spatial-grid/floor-placed-elevation.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/floor-placed-elevation.js +7 -12
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts +4 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.d.ts.map +1 -0
- package/dist/hooks/spatial-grid/floor-placed-footprints.js +7 -0
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts +5 -8
- package/dist/hooks/spatial-grid/spatial-grid-manager.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-manager.js +23 -106
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts +2931 -2
- package/dist/hooks/spatial-grid/spatial-grid-sync.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/spatial-grid-sync.js +207 -30
- package/dist/hooks/spatial-grid/support-host-patch.d.ts +45 -1
- package/dist/hooks/spatial-grid/support-host-patch.d.ts.map +1 -1
- package/dist/hooks/spatial-grid/support-host-patch.js +174 -9
- package/dist/hooks/spatial-grid/use-spatial-query.d.ts +1 -1
- package/dist/hooks/spatial-grid/use-spatial-query.js +1 -1
- package/dist/index.d.ts +74 -64
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +74 -61
- package/dist/lib/asset-storage.d.ts.map +1 -1
- package/dist/lib/asset-storage.js +4 -1
- package/dist/lib/door-operation.d.ts +1 -1
- package/dist/lib/item-polygon-overlap.d.ts +6 -0
- package/dist/lib/item-polygon-overlap.d.ts.map +1 -0
- package/dist/lib/item-polygon-overlap.js +67 -0
- package/dist/lib/level-name.d.ts +1 -1
- package/dist/lib/measurement-geometry.d.ts +4 -4
- package/dist/lib/plan-footprint.d.ts +41 -0
- package/dist/lib/plan-footprint.d.ts.map +1 -0
- package/dist/lib/plan-footprint.js +58 -0
- package/dist/lib/polygon-union.d.ts +4 -0
- package/dist/lib/polygon-union.d.ts.map +1 -0
- package/dist/lib/polygon-union.js +306 -0
- package/dist/lib/roof-overlap.d.ts +32 -0
- package/dist/lib/roof-overlap.d.ts.map +1 -0
- package/dist/lib/roof-overlap.js +72 -0
- package/dist/lib/room-topology-index.d.ts +1 -1
- package/dist/lib/room-topology-index.js +1 -1
- package/dist/lib/selection-proxy.d.ts +1 -1
- package/dist/lib/slab-polygon.d.ts +36 -3
- package/dist/lib/slab-polygon.d.ts.map +1 -1
- package/dist/lib/slab-polygon.js +135 -29
- package/dist/lib/space-detection.d.ts +12 -1
- package/dist/lib/space-detection.d.ts.map +1 -1
- package/dist/lib/space-detection.js +58 -25
- package/dist/lib/terrain-brush.d.ts +1 -1
- package/dist/lib/terrain-brush.js +1 -1
- package/dist/lib/terrain-codec.d.ts +2 -2
- package/dist/lib/terrain-codec.js +1 -1
- package/dist/lib/terrain-raycast.d.ts +1 -1
- package/dist/lib/terrain-raycast.js +1 -1
- package/dist/lib/terrain-source.d.ts +3 -3
- package/dist/lib/terrain-source.js +3 -3
- package/dist/lib/terrain-support.d.ts +1 -1
- package/dist/lib/terrain-support.js +3 -3
- package/dist/lib/unit-containment.d.ts +19 -0
- package/dist/lib/unit-containment.d.ts.map +1 -0
- package/dist/lib/unit-containment.js +158 -0
- package/dist/lib/unit-report.d.ts +19 -0
- package/dist/lib/unit-report.d.ts.map +1 -0
- package/dist/lib/unit-report.js +36 -0
- package/dist/lib/wall-distance.d.ts +2 -2
- package/dist/lib/wall-distance.js +1 -1
- package/dist/lib/zone-quantities.d.ts +1 -1
- package/dist/lib/zone-quantities.js +7 -7
- package/dist/material-library.d.ts +1 -1
- package/dist/material-library.js +1 -1
- package/dist/procedural-items/fixtures.d.ts +261 -0
- package/dist/procedural-items/fixtures.d.ts.map +1 -0
- package/dist/procedural-items/fixtures.js +349 -0
- package/dist/procedural-items/index.d.ts +10 -0
- package/dist/procedural-items/index.d.ts.map +1 -0
- package/dist/procedural-items/index.js +9 -0
- package/dist/procedural-items/integration.d.ts +92 -0
- package/dist/procedural-items/integration.d.ts.map +1 -0
- package/dist/procedural-items/integration.js +19 -0
- package/dist/procedural-items/library-colors.d.ts +56 -0
- package/dist/procedural-items/library-colors.d.ts.map +1 -0
- package/dist/procedural-items/library-colors.js +84 -0
- package/dist/procedural-items/materials.d.ts +5 -0
- package/dist/procedural-items/materials.d.ts.map +1 -0
- package/dist/procedural-items/materials.js +47 -0
- package/dist/procedural-items/node.d.ts +280 -0
- package/dist/procedural-items/node.d.ts.map +1 -0
- package/dist/procedural-items/node.js +71 -0
- package/dist/procedural-items/placement.d.ts +7 -0
- package/dist/procedural-items/placement.d.ts.map +1 -0
- package/dist/procedural-items/placement.js +48 -0
- package/dist/procedural-items/query.d.ts +50 -0
- package/dist/procedural-items/query.d.ts.map +1 -0
- package/dist/procedural-items/query.js +298 -0
- package/dist/procedural-items/recipe.d.ts +144 -0
- package/dist/procedural-items/recipe.d.ts.map +1 -0
- package/dist/procedural-items/recipe.js +372 -0
- package/dist/procedural-items/spatial.d.ts +19 -0
- package/dist/procedural-items/spatial.d.ts.map +1 -0
- package/dist/procedural-items/spatial.js +39 -0
- package/dist/registry/__bench__/relations-resolver.bench.js +2 -2
- package/dist/registry/handles.d.ts +36 -7
- package/dist/registry/handles.d.ts.map +1 -1
- package/dist/registry/index.d.ts +6 -7
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/index.js +4 -5
- package/dist/registry/registry.d.ts +13 -6
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +37 -4
- package/dist/registry/relations-resolver.d.ts +2 -2
- package/dist/registry/relations-resolver.js +1 -1
- package/dist/registry/scene-api.d.ts +18 -2
- package/dist/registry/scene-api.d.ts.map +1 -1
- package/dist/registry/scene-api.js +50 -2
- package/dist/registry/subtree.d.ts +1 -1
- package/dist/registry/subtree.js +2 -2
- package/dist/registry/types.d.ts +246 -21
- package/dist/registry/types.d.ts.map +1 -1
- package/dist/registry/use-registry-version.js +1 -1
- package/dist/registry/validate-relations.d.ts +4 -0
- package/dist/registry/validate-relations.d.ts.map +1 -0
- package/dist/registry/validate-relations.js +22 -0
- package/dist/schema/__bench__/node-parsers.bench.d.ts +24 -0
- package/dist/schema/__bench__/node-parsers.bench.d.ts.map +1 -0
- package/dist/schema/__bench__/node-parsers.bench.js +314 -0
- package/dist/schema/__fixtures__/node-fixtures.d.ts +28 -0
- package/dist/schema/__fixtures__/node-fixtures.d.ts.map +1 -0
- package/dist/schema/__fixtures__/node-fixtures.js +127 -0
- package/dist/schema/base.d.ts +1 -1
- package/dist/schema/base.d.ts.map +1 -1
- package/dist/schema/base.js +9 -2
- package/dist/schema/collections.d.ts +1 -1
- package/dist/schema/collections.js +1 -1
- package/dist/schema/compiled-node-parsers.d.ts +40 -0
- package/dist/schema/compiled-node-parsers.d.ts.map +1 -0
- package/dist/schema/compiled-node-parsers.js +95 -0
- package/dist/schema/index.d.ts +73 -66
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +65 -57
- package/dist/schema/material.d.ts +1 -0
- package/dist/schema/material.d.ts.map +1 -1
- package/dist/schema/material.js +2 -1
- package/dist/schema/nodes/automatic-downspout.d.ts +17 -0
- package/dist/schema/nodes/automatic-downspout.d.ts.map +1 -0
- package/dist/schema/nodes/automatic-downspout.js +237 -0
- package/dist/schema/nodes/block.d.ts +107 -0
- package/dist/schema/nodes/block.d.ts.map +1 -0
- package/dist/schema/nodes/block.js +206 -0
- package/dist/schema/nodes/box-vent.d.ts +8 -2
- package/dist/schema/nodes/box-vent.d.ts.map +1 -1
- package/dist/schema/nodes/box-vent.js +4 -2
- package/dist/schema/nodes/building.d.ts +2 -2
- package/dist/schema/nodes/building.d.ts.map +1 -1
- package/dist/schema/nodes/building.js +8 -5
- package/dist/schema/nodes/cabinet.d.ts +26 -4
- package/dist/schema/nodes/cabinet.d.ts.map +1 -1
- package/dist/schema/nodes/cabinet.js +29 -8
- package/dist/schema/nodes/ceiling.d.ts +2 -2
- package/dist/schema/nodes/ceiling.js +5 -5
- package/dist/schema/nodes/chimney.d.ts +2 -2
- package/dist/schema/nodes/chimney.js +2 -2
- package/dist/schema/nodes/column.d.ts +7 -6
- package/dist/schema/nodes/column.d.ts.map +1 -1
- package/dist/schema/nodes/column.js +3 -2
- package/dist/schema/nodes/construction-dimension.d.ts +1 -1
- package/dist/schema/nodes/construction-dimension.js +2 -2
- package/dist/schema/nodes/cupola.d.ts +9 -1
- package/dist/schema/nodes/cupola.d.ts.map +1 -1
- package/dist/schema/nodes/cupola.js +4 -2
- package/dist/schema/nodes/door.d.ts +1 -1
- package/dist/schema/nodes/door.js +2 -2
- package/dist/schema/nodes/dormer.d.ts +45 -2
- package/dist/schema/nodes/dormer.d.ts.map +1 -1
- package/dist/schema/nodes/dormer.js +133 -9
- package/dist/schema/nodes/downspout.d.ts +11 -1
- package/dist/schema/nodes/downspout.d.ts.map +1 -1
- package/dist/schema/nodes/downspout.js +26 -2
- package/dist/schema/nodes/duct-fitting.d.ts +18 -1
- package/dist/schema/nodes/duct-fitting.d.ts.map +1 -1
- package/dist/schema/nodes/duct-fitting.js +26 -5
- package/dist/schema/nodes/duct-segment.d.ts +23 -1
- package/dist/schema/nodes/duct-segment.d.ts.map +1 -1
- package/dist/schema/nodes/duct-segment.js +21 -1
- package/dist/schema/nodes/duct-terminal.d.ts +1 -1
- package/dist/schema/nodes/duct-terminal.js +1 -1
- package/dist/schema/nodes/elevator.d.ts +1 -1
- package/dist/schema/nodes/elevator.js +2 -2
- package/dist/schema/nodes/eyebrow-vent.d.ts +8 -2
- package/dist/schema/nodes/eyebrow-vent.d.ts.map +1 -1
- package/dist/schema/nodes/eyebrow-vent.js +4 -2
- package/dist/schema/nodes/fence.d.ts +1 -1
- package/dist/schema/nodes/fence.js +2 -2
- package/dist/schema/nodes/guide.d.ts +1 -1
- package/dist/schema/nodes/guide.js +2 -2
- package/dist/schema/nodes/gutter.d.ts +36 -2
- package/dist/schema/nodes/gutter.d.ts.map +1 -1
- package/dist/schema/nodes/gutter.js +310 -3
- package/dist/schema/nodes/hanger-overrides.d.ts +7 -0
- package/dist/schema/nodes/hanger-overrides.d.ts.map +1 -0
- package/dist/schema/nodes/hanger-overrides.js +6 -0
- package/dist/schema/nodes/hvac-equipment.d.ts +1 -1
- package/dist/schema/nodes/hvac-equipment.js +1 -1
- package/dist/schema/nodes/imported-mesh.d.ts +40 -0
- package/dist/schema/nodes/imported-mesh.d.ts.map +1 -0
- package/dist/schema/nodes/imported-mesh.js +27 -0
- package/dist/schema/nodes/item.d.ts +3 -2
- package/dist/schema/nodes/item.d.ts.map +1 -1
- package/dist/schema/nodes/item.js +8 -3
- package/dist/schema/nodes/lean-to-extension.d.ts +212 -0
- package/dist/schema/nodes/lean-to-extension.d.ts.map +1 -0
- package/dist/schema/nodes/lean-to-extension.js +114 -0
- package/dist/schema/nodes/level.d.ts +2 -2
- package/dist/schema/nodes/level.d.ts.map +1 -1
- package/dist/schema/nodes/level.js +1 -1
- package/dist/schema/nodes/lineset.d.ts +1 -1
- package/dist/schema/nodes/lineset.js +1 -1
- package/dist/schema/nodes/liquid-line.d.ts +1 -1
- package/dist/schema/nodes/liquid-line.js +1 -1
- package/dist/schema/nodes/measurement.d.ts +1 -1
- package/dist/schema/nodes/measurement.js +2 -2
- package/dist/schema/nodes/pipe-fitting.d.ts +10 -2
- package/dist/schema/nodes/pipe-fitting.d.ts.map +1 -1
- package/dist/schema/nodes/pipe-fitting.js +7 -3
- package/dist/schema/nodes/pipe-segment.d.ts +24 -2
- package/dist/schema/nodes/pipe-segment.d.ts.map +1 -1
- package/dist/schema/nodes/pipe-segment.js +21 -1
- package/dist/schema/nodes/pipe-trap.d.ts +2 -2
- package/dist/schema/nodes/pipe-trap.js +1 -1
- package/dist/schema/nodes/ridge-vent.d.ts +2 -2
- package/dist/schema/nodes/ridge-vent.d.ts.map +1 -1
- package/dist/schema/nodes/ridge-vent.js +7 -4
- package/dist/schema/nodes/roof-segment-shape.d.ts +5 -1
- package/dist/schema/nodes/roof-segment-shape.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment-shape.js +65 -2
- package/dist/schema/nodes/roof-segment-walls.d.ts +4 -2
- package/dist/schema/nodes/roof-segment-walls.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment-walls.js +2 -2
- package/dist/schema/nodes/roof-segment.d.ts +42 -2
- package/dist/schema/nodes/roof-segment.d.ts.map +1 -1
- package/dist/schema/nodes/roof-segment.js +81 -4
- package/dist/schema/nodes/roof.d.ts +23 -2
- package/dist/schema/nodes/roof.d.ts.map +1 -1
- package/dist/schema/nodes/roof.js +17 -3
- package/dist/schema/nodes/scan.d.ts +19 -2
- package/dist/schema/nodes/scan.d.ts.map +1 -1
- package/dist/schema/nodes/scan.js +13 -3
- package/dist/schema/nodes/shelf.d.ts +3 -3
- package/dist/schema/nodes/shelf.d.ts.map +1 -1
- package/dist/schema/nodes/shelf.js +3 -4
- package/dist/schema/nodes/site.d.ts +1 -1
- package/dist/schema/nodes/site.js +2 -2
- package/dist/schema/nodes/skylight.d.ts +5 -5
- package/dist/schema/nodes/skylight.js +2 -2
- package/dist/schema/nodes/slab.d.ts +1 -1
- package/dist/schema/nodes/slab.js +3 -3
- package/dist/schema/nodes/solar-panel.d.ts +1 -1
- package/dist/schema/nodes/solar-panel.js +3 -3
- package/dist/schema/nodes/spawn.d.ts +1 -1
- package/dist/schema/nodes/spawn.js +1 -1
- package/dist/schema/nodes/stair-segment.d.ts +1 -1
- package/dist/schema/nodes/stair-segment.js +2 -2
- package/dist/schema/nodes/stair.d.ts +2 -2
- package/dist/schema/nodes/stair.js +3 -3
- package/dist/schema/nodes/structural-grid.d.ts +1 -1
- package/dist/schema/nodes/structural-grid.js +1 -1
- package/dist/schema/nodes/turbine-vent.d.ts +8 -2
- package/dist/schema/nodes/turbine-vent.d.ts.map +1 -1
- package/dist/schema/nodes/turbine-vent.js +4 -2
- package/dist/schema/nodes/unit.d.ts +33 -0
- package/dist/schema/nodes/unit.d.ts.map +1 -0
- package/dist/schema/nodes/unit.js +13 -0
- package/dist/schema/nodes/wall.d.ts +5 -5
- package/dist/schema/nodes/wall.d.ts.map +1 -1
- package/dist/schema/nodes/wall.js +13 -6
- package/dist/schema/nodes/window.d.ts +10 -3
- package/dist/schema/nodes/window.d.ts.map +1 -1
- package/dist/schema/nodes/window.js +6 -2
- package/dist/schema/nodes/zone.d.ts +2 -2
- package/dist/schema/nodes/zone.js +2 -2
- package/dist/schema/scene-material.js +2 -2
- package/dist/schema/types.d.ts +815 -118
- package/dist/schema/types.d.ts.map +1 -1
- package/dist/schema/types.js +79 -46
- package/dist/services/alignment-anchors.d.ts +6 -11
- package/dist/services/alignment-anchors.d.ts.map +1 -1
- package/dist/services/alignment-anchors.js +7 -34
- package/dist/services/drag-session.d.ts +4 -4
- package/dist/services/drag-session.js +1 -1
- package/dist/services/hosting.d.ts +4 -10
- package/dist/services/hosting.d.ts.map +1 -1
- package/dist/services/hosting.js +6 -16
- package/dist/services/index.d.ts +16 -13
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +16 -13
- package/dist/services/level-height.d.ts +2 -2
- package/dist/services/level-height.js +3 -3
- package/dist/services/movement.d.ts +3 -3
- package/dist/services/movement.js +2 -2
- package/dist/services/port-connectivity.d.ts +1 -1
- package/dist/services/port-connectivity.js +1 -1
- package/dist/services/riser-diagram.d.ts +1 -1
- package/dist/services/shelf-board.d.ts +5 -0
- package/dist/services/shelf-board.d.ts.map +1 -0
- package/dist/services/shelf-board.js +15 -0
- package/dist/services/storey.d.ts +2 -2
- package/dist/services/storey.js +2 -2
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts +13 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-procedural-parity.fixtures.js +4691 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts +1060 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.d.ts.map +1 -0
- package/dist/services/surface-hosting-shelf-parity.fixtures.js +3127 -0
- package/dist/services/surface-hosting.d.ts +88 -0
- package/dist/services/surface-hosting.d.ts.map +1 -0
- package/dist/services/surface-hosting.js +268 -0
- package/dist/services/surface-region.d.ts +8 -0
- package/dist/services/surface-region.d.ts.map +1 -0
- package/dist/services/surface-region.js +44 -0
- package/dist/services/system-graph.d.ts +12 -1
- package/dist/services/system-graph.d.ts.map +1 -1
- package/dist/services/system-graph.js +36 -6
- package/dist/services/validate-dwv.d.ts +1 -1
- package/dist/services/validate-dwv.js +1 -1
- package/dist/store/actions/node-actions.d.ts +9 -2
- package/dist/store/actions/node-actions.d.ts.map +1 -1
- package/dist/store/actions/node-actions.js +475 -24
- package/dist/store/history-control.d.ts +3 -3
- package/dist/store/history-invalidation.d.ts +3 -0
- package/dist/store/history-invalidation.d.ts.map +1 -0
- package/dist/store/history-invalidation.js +72 -0
- package/dist/store/scene-hydration.d.ts +5 -0
- package/dist/store/scene-hydration.d.ts.map +1 -0
- package/dist/store/scene-hydration.js +57 -0
- package/dist/store/use-interactive.d.ts +2 -2
- package/dist/store/use-live-terrain.d.ts +1 -1
- package/dist/store/use-scene.d.ts +7 -4
- package/dist/store/use-scene.d.ts.map +1 -1
- package/dist/store/use-scene.js +361 -87
- package/dist/systems/elevator/elevator-dispatch.d.ts +2 -2
- package/dist/systems/elevator/elevator-dispatch.js +1 -1
- package/dist/systems/elevator/elevator-geometry.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.d.ts +1 -1
- package/dist/systems/elevator/elevator-opening-sync.js +2 -2
- package/dist/systems/elevator/elevator-opening-system.js +3 -3
- package/dist/systems/elevator/elevator-runtime.d.ts +3 -3
- package/dist/systems/elevator/elevator-runtime.js +3 -3
- package/dist/systems/elevator/elevator-service.d.ts +1 -1
- package/dist/systems/elevator/elevator-service.js +1 -1
- package/dist/systems/fence/fence-centerline.d.ts +2 -2
- package/dist/systems/fence/fence-centerline.js +2 -2
- package/dist/systems/fence/fence-spline.d.ts +2 -2
- package/dist/systems/roof/roof-elevation-system.d.ts +3 -0
- package/dist/systems/roof/roof-elevation-system.d.ts.map +1 -0
- package/dist/systems/roof/roof-elevation-system.js +94 -0
- package/dist/systems/roof/roof-elevation.d.ts +4 -0
- package/dist/systems/roof/roof-elevation.d.ts.map +1 -0
- package/dist/systems/roof/roof-elevation.js +95 -0
- package/dist/systems/roof/roof-footprint.d.ts +17 -0
- package/dist/systems/roof/roof-footprint.d.ts.map +1 -0
- package/dist/systems/roof/roof-footprint.js +83 -0
- package/dist/systems/slab/slab-placement.d.ts +1 -1
- package/dist/systems/slab/slab-support.d.ts +1 -1
- package/dist/systems/slab/slab-support.js +4 -4
- package/dist/systems/stair/stair-flight.d.ts +17 -0
- package/dist/systems/stair/stair-flight.d.ts.map +1 -0
- package/dist/systems/stair/stair-flight.js +27 -0
- package/dist/systems/stair/stair-footprint.d.ts +1 -1
- package/dist/systems/stair/stair-opening-preview.d.ts +1621 -1267
- package/dist/systems/stair/stair-opening-preview.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-preview.js +2 -2
- package/dist/systems/stair/stair-opening-sync.d.ts +1 -1
- package/dist/systems/stair/stair-opening-sync.js +6 -6
- package/dist/systems/stair/stair-opening-system.d.ts +1 -0
- package/dist/systems/stair/stair-opening-system.d.ts.map +1 -1
- package/dist/systems/stair/stair-opening-system.js +100 -103
- package/dist/systems/stair/stair-rise.d.ts +1 -1
- package/dist/systems/stair/stair-rise.d.ts.map +1 -1
- package/dist/systems/stair/stair-rise.js +23 -24
- package/dist/systems/wall/wall-curve.d.ts +3 -2
- package/dist/systems/wall/wall-curve.d.ts.map +1 -1
- package/dist/systems/wall/wall-curve.js +73 -0
- package/dist/systems/wall/wall-footprint.d.ts +3 -2
- package/dist/systems/wall/wall-footprint.d.ts.map +1 -1
- package/dist/systems/wall/wall-footprint.js +3 -2
- package/dist/systems/wall/wall-mitering.d.ts +1 -1
- package/dist/systems/wall/wall-mitering.js +1 -1
- package/dist/systems/wall/wall-move.d.ts +1 -1
- package/dist/systems/wall/wall-top.d.ts +1 -1
- package/dist/systems/wall/wall-topology.d.ts +2 -2
- package/dist/systems/wall/wall-topology.js +4 -4
- package/dist/utils/clone-scene-graph.d.ts +3 -3
- package/dist/utils/clone-scene-graph.d.ts.map +1 -1
- package/dist/utils/clone-scene-graph.js +35 -3
- package/dist/utils/scene-migrations.d.ts +3 -3
- package/dist/utils/scene-migrations.js +3 -3
- package/dist/utils/vertical-scene-migration.js +5 -5
- package/dist/validation/validate-build-json.d.ts +7 -1
- package/dist/validation/validate-build-json.d.ts.map +1 -1
- package/dist/validation/validate-build-json.js +92 -4
- package/package.json +23 -5
- package/dist/systems/elevator/elevator-runtime-system.d.ts +0 -2
- package/dist/systems/elevator/elevator-runtime-system.d.ts.map +0 -1
- package/dist/systems/elevator/elevator-runtime-system.js +0 -8
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const MetadataSchema = z.record(z.string(), z.unknown());
|
|
3
|
+
export const CaptureSessionLocatorSchema = z.object({
|
|
4
|
+
sessionId: z.string().min(1),
|
|
5
|
+
manifestUrl: z.string().min(1).optional(),
|
|
6
|
+
schemaVersion: z.number().int().positive().optional(),
|
|
7
|
+
revisionId: z.string().min(1).optional(),
|
|
8
|
+
});
|
|
9
|
+
export const DeviceMotionSampleSchema = z.object({
|
|
10
|
+
segment: z.number().int().nonnegative(),
|
|
11
|
+
timestamp: z.number().nonnegative(),
|
|
12
|
+
transform: z.array(z.number()).length(16),
|
|
13
|
+
});
|
|
14
|
+
export const DeviceMotionTrajectorySchema = z.object({
|
|
15
|
+
coordinateSystem: z.string().min(1),
|
|
16
|
+
samples: z.array(DeviceMotionSampleSchema).min(2),
|
|
17
|
+
});
|
|
18
|
+
export const ArkitDeviceMotionTrajectorySchema = DeviceMotionTrajectorySchema.extend({
|
|
19
|
+
coordinateSystem: z.literal('arkit-world'),
|
|
20
|
+
});
|
|
21
|
+
export const PointCloudPayloadSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
coordinateSystem: z.string().min(1),
|
|
24
|
+
positions: z.array(z.number().finite()).min(3),
|
|
25
|
+
colors: z.array(z.number().finite()).optional(),
|
|
26
|
+
})
|
|
27
|
+
.superRefine((payload, context) => {
|
|
28
|
+
if (payload.positions.length % 3 !== 0) {
|
|
29
|
+
context.addIssue({
|
|
30
|
+
code: 'custom',
|
|
31
|
+
message: 'Point-cloud positions must contain XYZ triples.',
|
|
32
|
+
path: ['positions'],
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (payload.colors && payload.colors.length !== payload.positions.length) {
|
|
36
|
+
context.addIssue({
|
|
37
|
+
code: 'custom',
|
|
38
|
+
message: 'Point-cloud colors must match the positions array length.',
|
|
39
|
+
path: ['colors'],
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
export const ArkitPointCloudPayloadSchema = PointCloudPayloadSchema.safeExtend({
|
|
44
|
+
coordinateSystem: z.literal('arkit-world'),
|
|
45
|
+
});
|
|
46
|
+
const MAX_SURFACE_MESH_VERTICES = 65_535;
|
|
47
|
+
const MAX_SURFACE_MESH_FACES = 20_000;
|
|
48
|
+
export const SurfaceMeshPayloadSchema = z
|
|
49
|
+
.object({
|
|
50
|
+
version: z.literal(1),
|
|
51
|
+
coordinateSystem: z.string().min(1),
|
|
52
|
+
representation: z.literal('quantized-indexed-triangle-mesh'),
|
|
53
|
+
appearance: z.literal('camera-vertex-color'),
|
|
54
|
+
vertexCount: z.number().int().positive().max(MAX_SURFACE_MESH_VERTICES),
|
|
55
|
+
faceCount: z.number().int().positive().max(MAX_SURFACE_MESH_FACES),
|
|
56
|
+
boundsMin: z.array(z.number().finite()).length(3),
|
|
57
|
+
boundsMax: z.array(z.number().finite()).length(3),
|
|
58
|
+
positionEncoding: z.literal('uint16x3-base64-little-endian'),
|
|
59
|
+
colorEncoding: z.literal('uint8x3-base64-srgb'),
|
|
60
|
+
indexEncoding: z.literal('uint16x3-base64-little-endian'),
|
|
61
|
+
positions: z.string().min(1).max(524_280),
|
|
62
|
+
colors: z.string().min(1).max(262_140),
|
|
63
|
+
indices: z
|
|
64
|
+
.string()
|
|
65
|
+
.min(1)
|
|
66
|
+
.max(MAX_SURFACE_MESH_FACES * 8),
|
|
67
|
+
})
|
|
68
|
+
.superRefine((payload, context) => {
|
|
69
|
+
if (payload.vertexCount > payload.faceCount * 3) {
|
|
70
|
+
context.addIssue({
|
|
71
|
+
code: 'custom',
|
|
72
|
+
message: 'Surface meshes cannot contain more than three vertices per face.',
|
|
73
|
+
path: ['vertexCount'],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
for (let axis = 0; axis < 3; axis += 1) {
|
|
77
|
+
if ((payload.boundsMax[axis] ?? 0) < (payload.boundsMin[axis] ?? 0)) {
|
|
78
|
+
context.addIssue({
|
|
79
|
+
code: 'custom',
|
|
80
|
+
message: 'Surface-mesh maximum bounds must not be below minimum bounds.',
|
|
81
|
+
path: ['boundsMax', axis],
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const positionBytes = decodeBase64(payload.positions);
|
|
86
|
+
const colorBytes = decodeBase64(payload.colors);
|
|
87
|
+
const indexBytes = decodeBase64(payload.indices);
|
|
88
|
+
validateSurfaceMeshByteLength(positionBytes, payload.vertexCount * 3 * 2, 'positions', context);
|
|
89
|
+
validateSurfaceMeshByteLength(colorBytes, payload.vertexCount * 3, 'colors', context);
|
|
90
|
+
validateSurfaceMeshByteLength(indexBytes, payload.faceCount * 3 * 2, 'indices', context);
|
|
91
|
+
if (indexBytes?.byteLength === payload.faceCount * 3 * 2) {
|
|
92
|
+
const indices = new DataView(indexBytes.buffer, indexBytes.byteOffset, indexBytes.byteLength);
|
|
93
|
+
for (let offset = 0; offset < indexBytes.byteLength; offset += 2) {
|
|
94
|
+
if (indices.getUint16(offset, true) >= payload.vertexCount) {
|
|
95
|
+
context.addIssue({
|
|
96
|
+
code: 'custom',
|
|
97
|
+
message: 'Surface-mesh indices must reference an existing vertex.',
|
|
98
|
+
path: ['indices'],
|
|
99
|
+
});
|
|
100
|
+
break;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
export const ArkitSurfaceMeshPayloadSchema = SurfaceMeshPayloadSchema.safeExtend({
|
|
106
|
+
coordinateSystem: z.literal('arkit-world'),
|
|
107
|
+
});
|
|
108
|
+
export const CaptureTimeRangeSchema = z
|
|
109
|
+
.object({
|
|
110
|
+
start: z.number().nonnegative(),
|
|
111
|
+
end: z.number().nonnegative(),
|
|
112
|
+
})
|
|
113
|
+
.refine((range) => range.end >= range.start, {
|
|
114
|
+
message: 'Capture time ranges must end at or after they start.',
|
|
115
|
+
path: ['end'],
|
|
116
|
+
});
|
|
117
|
+
export const CaptureArtifactReferenceSchema = z.object({
|
|
118
|
+
id: z.string().min(1),
|
|
119
|
+
uri: z.string().min(1).optional(),
|
|
120
|
+
mediaType: z.string().min(1),
|
|
121
|
+
byteLength: z.number().int().nonnegative().optional(),
|
|
122
|
+
sha256: z.string().min(1).optional(),
|
|
123
|
+
frameId: z.string().min(1).optional(),
|
|
124
|
+
timeRange: CaptureTimeRangeSchema.optional(),
|
|
125
|
+
metadata: MetadataSchema.optional(),
|
|
126
|
+
});
|
|
127
|
+
export const CaptureStreamDescriptorSchema = z.object({
|
|
128
|
+
id: z.string().min(1),
|
|
129
|
+
kind: z.string().min(1),
|
|
130
|
+
role: z.string().min(1).optional(),
|
|
131
|
+
availability: z.enum(['pending', 'live', 'ready', 'failed']).default('ready'),
|
|
132
|
+
frameId: z.string().min(1).optional(),
|
|
133
|
+
clockId: z.string().min(1).optional(),
|
|
134
|
+
artifact: CaptureArtifactReferenceSchema.optional(),
|
|
135
|
+
inline: z.unknown().optional(),
|
|
136
|
+
metadata: MetadataSchema.optional(),
|
|
137
|
+
});
|
|
138
|
+
export const CaptureClockSchema = z.object({
|
|
139
|
+
id: z.string().min(1),
|
|
140
|
+
timebase: z.enum(['seconds', 'milliseconds', 'microseconds', 'nanoseconds']),
|
|
141
|
+
epoch: z.string().min(1).optional(),
|
|
142
|
+
});
|
|
143
|
+
export const CaptureCoordinateFrameSchema = z.object({
|
|
144
|
+
id: z.string().min(1),
|
|
145
|
+
parentId: z.string().min(1).optional(),
|
|
146
|
+
convention: z.string().min(1),
|
|
147
|
+
transform: z.array(z.number()).length(16).optional(),
|
|
148
|
+
});
|
|
149
|
+
export const CaptureSessionManifestV1Schema = z.object({
|
|
150
|
+
schemaVersion: z.literal(1),
|
|
151
|
+
sessionId: z.string().min(1),
|
|
152
|
+
projectId: z.string().min(1),
|
|
153
|
+
streams: z.object({
|
|
154
|
+
roomModel: z
|
|
155
|
+
.object({
|
|
156
|
+
kind: z.literal('room-model'),
|
|
157
|
+
mediaType: z.literal('model/vnd.usdz+zip'),
|
|
158
|
+
url: z.string().min(1),
|
|
159
|
+
})
|
|
160
|
+
.optional(),
|
|
161
|
+
deviceMotion: z
|
|
162
|
+
.object({
|
|
163
|
+
kind: z.literal('device-motion'),
|
|
164
|
+
trajectory: ArkitDeviceMotionTrajectorySchema,
|
|
165
|
+
})
|
|
166
|
+
.optional(),
|
|
167
|
+
pointCloud: z
|
|
168
|
+
.object({
|
|
169
|
+
kind: z.literal('point-cloud'),
|
|
170
|
+
points: ArkitPointCloudPayloadSchema,
|
|
171
|
+
})
|
|
172
|
+
.optional(),
|
|
173
|
+
surfaceMesh: z
|
|
174
|
+
.object({
|
|
175
|
+
kind: z.literal('surface-mesh'),
|
|
176
|
+
mesh: ArkitSurfaceMeshPayloadSchema,
|
|
177
|
+
})
|
|
178
|
+
.optional(),
|
|
179
|
+
}),
|
|
180
|
+
});
|
|
181
|
+
export const CaptureSessionManifestV2Schema = z
|
|
182
|
+
.object({
|
|
183
|
+
schemaVersion: z.literal(2),
|
|
184
|
+
sessionId: z.string().min(1),
|
|
185
|
+
projectId: z.string().min(1).optional(),
|
|
186
|
+
revisionId: z.string().min(1).optional(),
|
|
187
|
+
state: z.enum(['live', 'finalizing', 'ready', 'failed']).default('ready'),
|
|
188
|
+
clocks: z.array(CaptureClockSchema).default([]),
|
|
189
|
+
coordinateFrames: z.array(CaptureCoordinateFrameSchema).default([]),
|
|
190
|
+
streams: z.array(CaptureStreamDescriptorSchema),
|
|
191
|
+
metadata: MetadataSchema.optional(),
|
|
192
|
+
})
|
|
193
|
+
.superRefine(validateUniqueSessionIds);
|
|
194
|
+
export const CaptureSessionManifestSchema = z.union([
|
|
195
|
+
CaptureSessionManifestV1Schema,
|
|
196
|
+
CaptureSessionManifestV2Schema,
|
|
197
|
+
]);
|
|
198
|
+
export const CaptureSessionDescriptorSchema = z
|
|
199
|
+
.object({
|
|
200
|
+
schemaVersion: z.number().int().positive(),
|
|
201
|
+
sessionId: z.string().min(1),
|
|
202
|
+
projectId: z.string().min(1).optional(),
|
|
203
|
+
revisionId: z.string().min(1).optional(),
|
|
204
|
+
state: z.enum(['live', 'finalizing', 'ready', 'failed']),
|
|
205
|
+
clocks: z.array(CaptureClockSchema),
|
|
206
|
+
coordinateFrames: z.array(CaptureCoordinateFrameSchema),
|
|
207
|
+
streams: z.array(CaptureStreamDescriptorSchema),
|
|
208
|
+
metadata: MetadataSchema.optional(),
|
|
209
|
+
})
|
|
210
|
+
.superRefine(validateUniqueSessionIds);
|
|
211
|
+
export function normalizeCaptureSessionManifest(value) {
|
|
212
|
+
const manifest = CaptureSessionManifestSchema.parse(value);
|
|
213
|
+
if (manifest.schemaVersion === 2)
|
|
214
|
+
return CaptureSessionDescriptorSchema.parse(manifest);
|
|
215
|
+
const streams = [];
|
|
216
|
+
if (manifest.streams.roomModel) {
|
|
217
|
+
streams.push({
|
|
218
|
+
id: 'room-model',
|
|
219
|
+
kind: manifest.streams.roomModel.kind,
|
|
220
|
+
role: 'model',
|
|
221
|
+
availability: 'ready',
|
|
222
|
+
artifact: {
|
|
223
|
+
id: `${manifest.sessionId}:room-model`,
|
|
224
|
+
mediaType: manifest.streams.roomModel.mediaType,
|
|
225
|
+
uri: manifest.streams.roomModel.url,
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
if (manifest.streams.deviceMotion) {
|
|
230
|
+
streams.push({
|
|
231
|
+
id: 'device-motion',
|
|
232
|
+
kind: manifest.streams.deviceMotion.kind,
|
|
233
|
+
role: 'deviceMotion',
|
|
234
|
+
availability: 'ready',
|
|
235
|
+
inline: manifest.streams.deviceMotion.trajectory,
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
if (manifest.streams.pointCloud) {
|
|
239
|
+
streams.push({
|
|
240
|
+
id: 'point-cloud',
|
|
241
|
+
kind: manifest.streams.pointCloud.kind,
|
|
242
|
+
role: 'pointCloud',
|
|
243
|
+
availability: 'ready',
|
|
244
|
+
inline: manifest.streams.pointCloud.points,
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
if (manifest.streams.surfaceMesh) {
|
|
248
|
+
streams.push({
|
|
249
|
+
id: 'surface-mesh',
|
|
250
|
+
kind: manifest.streams.surfaceMesh.kind,
|
|
251
|
+
role: 'surfaceMesh',
|
|
252
|
+
availability: 'ready',
|
|
253
|
+
inline: manifest.streams.surfaceMesh.mesh,
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return CaptureSessionDescriptorSchema.parse({
|
|
257
|
+
schemaVersion: manifest.schemaVersion,
|
|
258
|
+
sessionId: manifest.sessionId,
|
|
259
|
+
projectId: manifest.projectId,
|
|
260
|
+
state: 'ready',
|
|
261
|
+
clocks: [],
|
|
262
|
+
coordinateFrames: [],
|
|
263
|
+
streams,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
export function captureLayerKey(stream) {
|
|
267
|
+
if (stream.role)
|
|
268
|
+
return stream.role;
|
|
269
|
+
if (stream.kind === 'room-model')
|
|
270
|
+
return 'model';
|
|
271
|
+
if (stream.kind === 'device-motion')
|
|
272
|
+
return 'deviceMotion';
|
|
273
|
+
if (stream.kind === 'point-cloud')
|
|
274
|
+
return 'pointCloud';
|
|
275
|
+
if (stream.kind === 'surface-mesh')
|
|
276
|
+
return 'surfaceMesh';
|
|
277
|
+
if (stream.kind === 'gaussian-splat')
|
|
278
|
+
return 'splat';
|
|
279
|
+
if (stream.kind === 'spaceform-scene')
|
|
280
|
+
return 'spaceformScene';
|
|
281
|
+
return stream.kind;
|
|
282
|
+
}
|
|
283
|
+
export function captureStreamLabel(stream) {
|
|
284
|
+
const key = captureLayerKey(stream);
|
|
285
|
+
if (key === 'model')
|
|
286
|
+
return '3D model';
|
|
287
|
+
if (key === 'deviceMotion')
|
|
288
|
+
return 'Device motion';
|
|
289
|
+
if (key === 'pointCloud')
|
|
290
|
+
return 'Point cloud';
|
|
291
|
+
if (key === 'surfaceMesh')
|
|
292
|
+
return 'Surface mesh';
|
|
293
|
+
if (key === 'splat')
|
|
294
|
+
return 'Gaussian splat';
|
|
295
|
+
return key
|
|
296
|
+
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
297
|
+
.replace(/[-_]+/g, ' ')
|
|
298
|
+
.replace(/^./, (value) => value.toUpperCase());
|
|
299
|
+
}
|
|
300
|
+
function validateSurfaceMeshByteLength(bytes, expectedLength, path, context) {
|
|
301
|
+
if (bytes?.byteLength === expectedLength)
|
|
302
|
+
return;
|
|
303
|
+
context.addIssue({
|
|
304
|
+
code: 'custom',
|
|
305
|
+
message: `Surface-mesh ${path} must contain exactly ${expectedLength} decoded bytes.`,
|
|
306
|
+
path: [path],
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
function decodeBase64(value) {
|
|
310
|
+
if (value.length % 4 !== 0 ||
|
|
311
|
+
!/^(?:[A-Za-z\d+/]{4})*(?:[A-Za-z\d+/]{2}==|[A-Za-z\d+/]{3}=)?$/.test(value)) {
|
|
312
|
+
return null;
|
|
313
|
+
}
|
|
314
|
+
const alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
315
|
+
const padding = value.endsWith('==') ? 2 : value.endsWith('=') ? 1 : 0;
|
|
316
|
+
const output = new Uint8Array((value.length / 4) * 3 - padding);
|
|
317
|
+
let outputIndex = 0;
|
|
318
|
+
for (let index = 0; index < value.length; index += 4) {
|
|
319
|
+
const a = alphabet.indexOf(value[index] ?? '');
|
|
320
|
+
const b = alphabet.indexOf(value[index + 1] ?? '');
|
|
321
|
+
const c = value[index + 2] === '=' ? 0 : alphabet.indexOf(value[index + 2] ?? '');
|
|
322
|
+
const d = value[index + 3] === '=' ? 0 : alphabet.indexOf(value[index + 3] ?? '');
|
|
323
|
+
const bits = a * 262_144 + b * 4096 + c * 64 + d;
|
|
324
|
+
if (outputIndex < output.length)
|
|
325
|
+
output[outputIndex++] = Math.floor(bits / 65_536) % 256;
|
|
326
|
+
if (outputIndex < output.length)
|
|
327
|
+
output[outputIndex++] = Math.floor(bits / 256) % 256;
|
|
328
|
+
if (outputIndex < output.length)
|
|
329
|
+
output[outputIndex++] = bits % 256;
|
|
330
|
+
}
|
|
331
|
+
return output;
|
|
332
|
+
}
|
|
333
|
+
function validateUniqueSessionIds(value, context) {
|
|
334
|
+
validateUniqueIds(value.streams, 'streams', context);
|
|
335
|
+
validateUniqueIds(value.clocks, 'clocks', context);
|
|
336
|
+
validateUniqueIds(value.coordinateFrames, 'coordinateFrames', context);
|
|
337
|
+
}
|
|
338
|
+
function validateUniqueIds(values, path, context) {
|
|
339
|
+
const seen = new Set();
|
|
340
|
+
values.forEach((value, index) => {
|
|
341
|
+
if (seen.has(value.id)) {
|
|
342
|
+
context.addIssue({
|
|
343
|
+
code: 'custom',
|
|
344
|
+
message: `Duplicate capture ${path} id: ${value.id}`,
|
|
345
|
+
path: [path, index, 'id'],
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
seen.add(value.id);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { type CaptureArtifactReference, type CaptureSessionDescriptor, type CaptureSessionLocator } from './schema.js';
|
|
3
|
+
export declare const CaptureStreamPacketSchema: z.ZodObject<{
|
|
4
|
+
protocolVersion: z.ZodLiteral<1>;
|
|
5
|
+
sessionId: z.ZodString;
|
|
6
|
+
streamId: z.ZodString;
|
|
7
|
+
generation: z.ZodNumber;
|
|
8
|
+
sequence: z.ZodNumber;
|
|
9
|
+
timestamp: z.ZodNumber;
|
|
10
|
+
frameId: z.ZodOptional<z.ZodString>;
|
|
11
|
+
keyframe: z.ZodOptional<z.ZodBoolean>;
|
|
12
|
+
bounds: z.ZodOptional<z.ZodTuple<[z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber, z.ZodNumber], null>>;
|
|
13
|
+
payload: z.ZodUnknown;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export type CaptureStreamPacket = z.infer<typeof CaptureStreamPacketSchema>;
|
|
16
|
+
export type CaptureSourceEvent = {
|
|
17
|
+
type: 'descriptor';
|
|
18
|
+
descriptor: CaptureSessionDescriptor;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'packet';
|
|
21
|
+
packet: CaptureStreamPacket;
|
|
22
|
+
} | {
|
|
23
|
+
type: 'closed';
|
|
24
|
+
};
|
|
25
|
+
export type CaptureArtifactResolution = {
|
|
26
|
+
url: string;
|
|
27
|
+
dispose?: () => void;
|
|
28
|
+
};
|
|
29
|
+
export type CaptureSubscriptionOptions = {
|
|
30
|
+
signal?: AbortSignal;
|
|
31
|
+
streamIds?: readonly string[];
|
|
32
|
+
};
|
|
33
|
+
export interface CaptureSource {
|
|
34
|
+
describe(signal?: AbortSignal): Promise<CaptureSessionDescriptor>;
|
|
35
|
+
resolveArtifact?(artifact: CaptureArtifactReference, signal?: AbortSignal): Promise<CaptureArtifactResolution>;
|
|
36
|
+
subscribe?(options?: CaptureSubscriptionOptions): AsyncIterable<CaptureSourceEvent>;
|
|
37
|
+
}
|
|
38
|
+
export type CaptureSourceResolver = (locator: CaptureSessionLocator) => CaptureSource | Promise<CaptureSource>;
|
|
39
|
+
export type HttpCaptureSourceOptions = {
|
|
40
|
+
credentials?: RequestCredentials;
|
|
41
|
+
fetch?: typeof globalThis.fetch;
|
|
42
|
+
headers?: HeadersInit;
|
|
43
|
+
manifestUrl?: (locator: CaptureSessionLocator) => string;
|
|
44
|
+
resolveArtifact?: (artifact: CaptureArtifactReference, signal?: AbortSignal) => Promise<CaptureArtifactResolution>;
|
|
45
|
+
};
|
|
46
|
+
export type PushCaptureSourceOptions = {
|
|
47
|
+
maxQueuedEventsPerSubscriber?: number;
|
|
48
|
+
};
|
|
49
|
+
export declare function createHttpCaptureSource(locatorInput: CaptureSessionLocator, options?: HttpCaptureSourceOptions): CaptureSource;
|
|
50
|
+
export declare class PushCaptureSource implements CaptureSource {
|
|
51
|
+
#private;
|
|
52
|
+
constructor(descriptor: CaptureSessionDescriptor, options?: PushCaptureSourceOptions);
|
|
53
|
+
describe(): Promise<CaptureSessionDescriptor>;
|
|
54
|
+
resolveArtifact(artifact: CaptureArtifactReference): Promise<CaptureArtifactResolution>;
|
|
55
|
+
subscribe(options?: CaptureSubscriptionOptions): AsyncIterable<CaptureSourceEvent>;
|
|
56
|
+
updateDescriptor(descriptor: CaptureSessionDescriptor): void;
|
|
57
|
+
publishPacket(packetInput: CaptureStreamPacket): void;
|
|
58
|
+
close(): void;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=source.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../../src/capture/source.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EACL,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAE7B,KAAK,qBAAqB,EAG3B,MAAM,UAAU,CAAA;AAEjB,eAAO,MAAM,yBAAyB;;;;;;;;;;;iBAapC,CAAA;AAEF,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAA;AAE3E,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,wBAAwB,CAAA;CAAE,GAC5D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,CAAA;AAEtB,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAC9B,CAAA;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,wBAAwB,CAAC,CAAA;IACjE,eAAe,CAAC,CACd,QAAQ,EAAE,wBAAwB,EAClC,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,yBAAyB,CAAC,CAAA;IACrC,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE,0BAA0B,GAAG,aAAa,CAAC,kBAAkB,CAAC,CAAA;CACpF;AAED,MAAM,MAAM,qBAAqB,GAAG,CAClC,OAAO,EAAE,qBAAqB,KAC3B,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;AAE3C,MAAM,MAAM,wBAAwB,GAAG;IACrC,WAAW,CAAC,EAAE,kBAAkB,CAAA;IAChC,KAAK,CAAC,EAAE,OAAO,UAAU,CAAC,KAAK,CAAA;IAC/B,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,MAAM,CAAA;IACxD,eAAe,CAAC,EAAE,CAChB,QAAQ,EAAE,wBAAwB,EAClC,MAAM,CAAC,EAAE,WAAW,KACjB,OAAO,CAAC,yBAAyB,CAAC,CAAA;CACxC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,4BAA4B,CAAC,EAAE,MAAM,CAAA;CACtC,CAAA;AAED,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,qBAAqB,EACnC,OAAO,GAAE,wBAA6B,GACrC,aAAa,CAwCf;AAmCD,qBAAa,iBAAkB,YAAW,aAAa;;gBAMzC,UAAU,EAAE,wBAAwB,EAAE,OAAO,GAAE,wBAA6B;IAKlF,QAAQ,IAAI,OAAO,CAAC,wBAAwB,CAAC;IAI7C,eAAe,CAAC,QAAQ,EAAE,wBAAwB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAK7F,SAAS,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAAC,kBAAkB,CAAC;IAyBtF,gBAAgB,CAAC,UAAU,EAAE,wBAAwB,GAAG,IAAI;IAU5D,aAAa,CAAC,WAAW,EAAE,mBAAmB,GAAG,IAAI;IAYrD,KAAK,IAAI,IAAI;CAqBd"}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { CaptureSessionDescriptorSchema, CaptureSessionLocatorSchema, normalizeCaptureSessionManifest, } from './schema.js';
|
|
3
|
+
export const CaptureStreamPacketSchema = z.object({
|
|
4
|
+
protocolVersion: z.literal(1),
|
|
5
|
+
sessionId: z.string().min(1),
|
|
6
|
+
streamId: z.string().min(1),
|
|
7
|
+
generation: z.number().int().nonnegative(),
|
|
8
|
+
sequence: z.number().int().nonnegative(),
|
|
9
|
+
timestamp: z.number().nonnegative(),
|
|
10
|
+
frameId: z.string().min(1).optional(),
|
|
11
|
+
keyframe: z.boolean().optional(),
|
|
12
|
+
bounds: z
|
|
13
|
+
.tuple([z.number(), z.number(), z.number(), z.number(), z.number(), z.number()])
|
|
14
|
+
.optional(),
|
|
15
|
+
payload: z.unknown(),
|
|
16
|
+
});
|
|
17
|
+
export function createHttpCaptureSource(locatorInput, options = {}) {
|
|
18
|
+
const locator = CaptureSessionLocatorSchema.parse(locatorInput);
|
|
19
|
+
const manifestUrl = locator.manifestUrl ?? options.manifestUrl?.(locator);
|
|
20
|
+
if (!manifestUrl)
|
|
21
|
+
throw new Error(`Capture session ${locator.sessionId} has no manifest URL.`);
|
|
22
|
+
let descriptorPromise = null;
|
|
23
|
+
const loadDescriptor = async () => {
|
|
24
|
+
const fetcher = options.fetch ?? globalThis.fetch;
|
|
25
|
+
const response = await fetcher(manifestUrl, {
|
|
26
|
+
credentials: options.credentials,
|
|
27
|
+
headers: options.headers,
|
|
28
|
+
});
|
|
29
|
+
if (!response.ok)
|
|
30
|
+
throw new Error(`Capture session ${locator.sessionId} is unavailable.`);
|
|
31
|
+
const descriptor = normalizeCaptureSessionManifest(await response.json());
|
|
32
|
+
if (descriptor.sessionId !== locator.sessionId) {
|
|
33
|
+
throw new Error(`Capture manifest session does not match ${locator.sessionId}.`);
|
|
34
|
+
}
|
|
35
|
+
if (locator.schemaVersion && descriptor.schemaVersion !== locator.schemaVersion) {
|
|
36
|
+
throw new Error(`Capture manifest schema does not match version ${locator.schemaVersion}.`);
|
|
37
|
+
}
|
|
38
|
+
if (locator.revisionId && descriptor.revisionId !== locator.revisionId) {
|
|
39
|
+
throw new Error(`Capture manifest revision does not match ${locator.revisionId}.`);
|
|
40
|
+
}
|
|
41
|
+
return descriptor;
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
describe(signal) {
|
|
45
|
+
descriptorPromise ??= loadDescriptor().catch((cause) => {
|
|
46
|
+
descriptorPromise = null;
|
|
47
|
+
throw cause;
|
|
48
|
+
});
|
|
49
|
+
return waitForPromise(descriptorPromise, signal).then(cloneCaptureDescriptor);
|
|
50
|
+
},
|
|
51
|
+
async resolveArtifact(artifact, signal) {
|
|
52
|
+
if (options.resolveArtifact)
|
|
53
|
+
return options.resolveArtifact(artifact, signal);
|
|
54
|
+
if (!artifact.uri)
|
|
55
|
+
throw new Error(`Capture artifact ${artifact.id} has no URI.`);
|
|
56
|
+
return { url: resolveArtifactUri(artifact.uri, manifestUrl) };
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function waitForPromise(promise, signal) {
|
|
61
|
+
if (!signal)
|
|
62
|
+
return promise;
|
|
63
|
+
if (signal.aborted)
|
|
64
|
+
return Promise.reject(abortError());
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
const onAbort = () => reject(abortError());
|
|
67
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
68
|
+
void promise.then(resolve, reject).finally(() => signal.removeEventListener('abort', onAbort));
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function abortError() {
|
|
72
|
+
const error = new Error('The capture request was aborted.');
|
|
73
|
+
error.name = 'AbortError';
|
|
74
|
+
return error;
|
|
75
|
+
}
|
|
76
|
+
function resolveArtifactUri(uri, manifestUrl) {
|
|
77
|
+
try {
|
|
78
|
+
const base = typeof globalThis.location === 'undefined'
|
|
79
|
+
? new URL(manifestUrl)
|
|
80
|
+
: new URL(manifestUrl, globalThis.location.href);
|
|
81
|
+
return new URL(uri, base).toString();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return uri;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export class PushCaptureSource {
|
|
88
|
+
#closed = false;
|
|
89
|
+
#descriptor;
|
|
90
|
+
#maxQueuedEventsPerSubscriber;
|
|
91
|
+
#subscribers = new Set();
|
|
92
|
+
constructor(descriptor, options = {}) {
|
|
93
|
+
this.#descriptor = cloneCaptureDescriptor(descriptor);
|
|
94
|
+
this.#maxQueuedEventsPerSubscriber = Math.max(1, options.maxQueuedEventsPerSubscriber ?? 32);
|
|
95
|
+
}
|
|
96
|
+
async describe() {
|
|
97
|
+
return cloneCaptureDescriptor(this.#descriptor);
|
|
98
|
+
}
|
|
99
|
+
async resolveArtifact(artifact) {
|
|
100
|
+
if (!artifact.uri)
|
|
101
|
+
throw new Error(`Capture artifact ${artifact.id} has no URI.`);
|
|
102
|
+
return { url: artifact.uri };
|
|
103
|
+
}
|
|
104
|
+
subscribe(options = {}) {
|
|
105
|
+
let cleanupAbort = () => { };
|
|
106
|
+
let subscriber;
|
|
107
|
+
const iterator = new EventIterator(() => {
|
|
108
|
+
cleanupAbort();
|
|
109
|
+
this.#subscribers.delete(subscriber);
|
|
110
|
+
}, this.#maxQueuedEventsPerSubscriber);
|
|
111
|
+
subscriber = {
|
|
112
|
+
iterator,
|
|
113
|
+
streamIds: options.streamIds ? new Set(options.streamIds) : null,
|
|
114
|
+
};
|
|
115
|
+
this.#subscribers.add(subscriber);
|
|
116
|
+
if (this.#closed) {
|
|
117
|
+
iterator.close({ type: 'closed' });
|
|
118
|
+
}
|
|
119
|
+
else if (options.signal) {
|
|
120
|
+
if (options.signal.aborted)
|
|
121
|
+
iterator.finish();
|
|
122
|
+
else {
|
|
123
|
+
const onAbort = () => iterator.finish();
|
|
124
|
+
options.signal.addEventListener('abort', onAbort, { once: true });
|
|
125
|
+
cleanupAbort = () => options.signal?.removeEventListener('abort', onAbort);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return iterator;
|
|
129
|
+
}
|
|
130
|
+
updateDescriptor(descriptor) {
|
|
131
|
+
if (this.#closed)
|
|
132
|
+
return;
|
|
133
|
+
const nextDescriptor = cloneCaptureDescriptor(descriptor);
|
|
134
|
+
if (nextDescriptor.sessionId !== this.#descriptor.sessionId) {
|
|
135
|
+
throw new Error('A capture source cannot change session identity.');
|
|
136
|
+
}
|
|
137
|
+
this.#descriptor = nextDescriptor;
|
|
138
|
+
this.#publish({ type: 'descriptor', descriptor: cloneCaptureDescriptor(nextDescriptor) });
|
|
139
|
+
}
|
|
140
|
+
publishPacket(packetInput) {
|
|
141
|
+
if (this.#closed)
|
|
142
|
+
return;
|
|
143
|
+
const packet = CaptureStreamPacketSchema.parse(packetInput);
|
|
144
|
+
if (packet.sessionId !== this.#descriptor.sessionId) {
|
|
145
|
+
throw new Error(`Capture packet does not belong to ${this.#descriptor.sessionId}.`);
|
|
146
|
+
}
|
|
147
|
+
if (!this.#descriptor.streams.some((stream) => stream.id === packet.streamId)) {
|
|
148
|
+
throw new Error(`Capture packet references unknown stream ${packet.streamId}.`);
|
|
149
|
+
}
|
|
150
|
+
this.#publish({ type: 'packet', packet });
|
|
151
|
+
}
|
|
152
|
+
close() {
|
|
153
|
+
if (this.#closed)
|
|
154
|
+
return;
|
|
155
|
+
this.#closed = true;
|
|
156
|
+
for (const subscriber of this.#subscribers) {
|
|
157
|
+
subscriber.iterator.close({ type: 'closed' });
|
|
158
|
+
}
|
|
159
|
+
this.#subscribers.clear();
|
|
160
|
+
}
|
|
161
|
+
#publish(event) {
|
|
162
|
+
for (const subscriber of this.#subscribers) {
|
|
163
|
+
if (event.type === 'packet' &&
|
|
164
|
+
subscriber.streamIds &&
|
|
165
|
+
!subscriber.streamIds.has(event.packet.streamId)) {
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
subscriber.iterator.push(cloneCaptureSourceEvent(event));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
class EventIterator {
|
|
173
|
+
#done = false;
|
|
174
|
+
#maxQueuedEvents;
|
|
175
|
+
#onFinish;
|
|
176
|
+
#queue = [];
|
|
177
|
+
#waiters = [];
|
|
178
|
+
constructor(onFinish, maxQueuedEvents) {
|
|
179
|
+
this.#onFinish = onFinish;
|
|
180
|
+
this.#maxQueuedEvents = maxQueuedEvents;
|
|
181
|
+
}
|
|
182
|
+
[Symbol.asyncIterator]() {
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
next() {
|
|
186
|
+
const event = this.#queue.shift();
|
|
187
|
+
if (event)
|
|
188
|
+
return Promise.resolve({ done: false, value: event });
|
|
189
|
+
if (this.#done)
|
|
190
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
191
|
+
return new Promise((resolve) => this.#waiters.push(resolve));
|
|
192
|
+
}
|
|
193
|
+
return() {
|
|
194
|
+
this.finish();
|
|
195
|
+
return Promise.resolve({ done: true, value: undefined });
|
|
196
|
+
}
|
|
197
|
+
push(event) {
|
|
198
|
+
if (this.#done)
|
|
199
|
+
return;
|
|
200
|
+
const waiter = this.#waiters.shift();
|
|
201
|
+
if (waiter)
|
|
202
|
+
waiter({ done: false, value: event });
|
|
203
|
+
else {
|
|
204
|
+
this.#queue.push(event);
|
|
205
|
+
this.#trimQueue();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
close(event) {
|
|
209
|
+
if (this.#done)
|
|
210
|
+
return;
|
|
211
|
+
this.#done = true;
|
|
212
|
+
this.#queue = [];
|
|
213
|
+
const waiter = this.#waiters.shift();
|
|
214
|
+
if (waiter)
|
|
215
|
+
waiter({ done: false, value: event });
|
|
216
|
+
else
|
|
217
|
+
this.#queue.push(event);
|
|
218
|
+
for (const pending of this.#waiters.splice(0))
|
|
219
|
+
pending({ done: true, value: undefined });
|
|
220
|
+
this.#onFinish();
|
|
221
|
+
}
|
|
222
|
+
finish() {
|
|
223
|
+
if (this.#done) {
|
|
224
|
+
this.#queue = [];
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
this.#done = true;
|
|
228
|
+
this.#queue = [];
|
|
229
|
+
this.#onFinish();
|
|
230
|
+
for (const waiter of this.#waiters.splice(0))
|
|
231
|
+
waiter({ done: true, value: undefined });
|
|
232
|
+
}
|
|
233
|
+
#trimQueue() {
|
|
234
|
+
while (this.#queue.length > this.#maxQueuedEvents) {
|
|
235
|
+
const packetIndex = this.#queue.findIndex((event) => event.type === 'packet');
|
|
236
|
+
this.#queue.splice(packetIndex >= 0 ? packetIndex : 0, 1);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function cloneCaptureDescriptor(descriptor) {
|
|
241
|
+
return CaptureSessionDescriptorSchema.parse(structuredClone(descriptor));
|
|
242
|
+
}
|
|
243
|
+
function cloneCaptureSourceEvent(event) {
|
|
244
|
+
if (event.type === 'descriptor') {
|
|
245
|
+
return { type: 'descriptor', descriptor: cloneCaptureDescriptor(event.descriptor) };
|
|
246
|
+
}
|
|
247
|
+
if (event.type === 'packet') {
|
|
248
|
+
return {
|
|
249
|
+
type: 'packet',
|
|
250
|
+
packet: CaptureStreamPacketSchema.parse(structuredClone(event.packet)),
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return { type: 'closed' };
|
|
254
|
+
}
|