@honua/app-platform 0.1.2-beta.0 → 0.1.7-beta.0
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/app/index.d.ts.map +1 -1
- package/app/index.js +4 -0
- package/collaboration/client.d.ts.map +1 -1
- package/connect-url-safety.d.ts +53 -0
- package/connect-url-safety.js +189 -0
- package/contract/discovery.d.ts +34 -0
- package/contract/discovery.d.ts.map +1 -1
- package/contract/index.d.ts +7 -5
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +3 -2
- package/contract/pmtiles.d.ts +10 -1
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +10 -2
- package/contract/protocol-module.d.ts +84 -9
- package/contract/protocol-module.d.ts.map +1 -1
- package/contract/query-filter-fes.d.ts +18 -0
- package/contract/query-filter-fes.d.ts.map +1 -0
- package/contract/query-filter-fes.js +122 -0
- package/contract/query-filter.d.ts +300 -0
- package/contract/query-filter.d.ts.map +1 -0
- package/contract/query-filter.js +883 -0
- package/contract/schema.d.ts +12 -0
- package/contract/schema.d.ts.map +1 -1
- package/contract/schema.js +34 -0
- package/contract/source-capability-support.d.ts.map +1 -1
- package/contract/source-capability-support.js +15 -3
- package/contract/source.d.ts +45 -25
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +719 -479
- package/contract/types.d.ts +88 -19
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +4 -0
- package/contract/widget-source.d.ts.map +1 -1
- package/controls/basemap-switcher.d.ts +19 -11
- package/controls/basemap-switcher.d.ts.map +1 -1
- package/controls/basemap-switcher.js +58 -25
- package/controls/catalog.d.ts +105 -0
- package/controls/catalog.d.ts.map +1 -0
- package/controls/catalog.js +341 -0
- package/controls/element-utils.d.ts +9 -0
- package/controls/element-utils.d.ts.map +1 -1
- package/controls/element-utils.js +17 -0
- package/controls/index.d.ts +29 -8
- package/controls/index.d.ts.map +1 -1
- package/controls/index.js +26 -8
- package/controls/layer-list.d.ts +13 -5
- package/controls/layer-list.d.ts.map +1 -1
- package/controls/layer-list.js +72 -15
- package/controls/legend.d.ts +32 -5
- package/controls/legend.d.ts.map +1 -1
- package/controls/legend.js +95 -25
- package/controls/qualification.d.ts +152 -0
- package/controls/qualification.d.ts.map +1 -0
- package/controls/qualification.js +1265 -0
- package/controls/registry.d.ts +104 -0
- package/controls/registry.d.ts.map +1 -0
- package/controls/registry.js +150 -0
- package/controls/swipe-control.d.ts +6 -1
- package/controls/swipe-control.d.ts.map +1 -1
- package/controls/swipe-control.js +82 -20
- package/core/client.d.ts +51 -21
- package/core/client.d.ts.map +1 -1
- package/core/client.js +234 -54
- package/core/error-classifications.d.ts +23 -0
- package/core/error-classifications.d.ts.map +1 -1
- package/core/error-classifications.js +23 -0
- package/core/error-code-registry.d.ts +24 -1
- package/core/error-code-registry.d.ts.map +1 -1
- package/core/error-code-registry.js +23 -0
- package/core/error-envelope.js +2 -0
- package/core/errors.d.ts +2 -2
- package/core/errors.d.ts.map +1 -1
- package/core/errors.js +1 -1
- package/core/geoparquet-sql.d.ts +69 -5
- package/core/geoparquet-sql.d.ts.map +1 -1
- package/core/geoparquet-sql.js +327 -10
- package/core/odata-write-codec.d.ts.map +1 -1
- package/core/odata-write-codec.js +0 -1
- package/core/odata.d.ts +6 -0
- package/core/odata.d.ts.map +1 -1
- package/core/odata.js +6 -1
- package/core/ogc-processes.d.ts +182 -25
- package/core/ogc-processes.d.ts.map +1 -1
- package/core/ogc-processes.js +602 -30
- package/core/process-runner.d.ts +8 -1
- package/core/process-runner.d.ts.map +1 -1
- package/core/process-runner.js +1 -0
- package/core/protocol-transport.d.ts +2 -0
- package/core/protocol-transport.d.ts.map +1 -1
- package/core/stac.d.ts +32 -0
- package/core/stac.d.ts.map +1 -1
- package/core/stac.js +158 -23
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +273 -68
- package/core/types.d.ts +138 -11
- package/core/types.d.ts.map +1 -1
- package/core/wfs-axis-order.d.ts +18 -0
- package/core/wfs-axis-order.d.ts.map +1 -0
- package/core/wfs-axis-order.js +108 -0
- package/core/wfs-capabilities.d.ts +65 -24
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +237 -27
- package/core/wfs-filter.d.ts +26 -3
- package/core/wfs-filter.d.ts.map +1 -1
- package/core/wfs-filter.js +48 -53
- package/core/wfs-protocol-error.d.ts +12 -0
- package/core/wfs-protocol-error.d.ts.map +1 -0
- package/core/wfs-protocol-error.js +13 -0
- package/core/wfs.d.ts +53 -1
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +251 -29
- package/core/wms-feature-info.d.ts +92 -0
- package/core/wms-feature-info.d.ts.map +1 -0
- package/core/wms-feature-info.js +285 -0
- package/core/wms.d.ts +9 -0
- package/core/wms.d.ts.map +1 -1
- package/core/wms.js +17 -5
- package/esri-compat/event-bus.d.ts +20 -0
- package/esri-compat/event-bus.d.ts.map +1 -1
- package/esri-compat/feature-filter.d.ts +46 -1
- package/esri-compat/feature-filter.d.ts.map +1 -1
- package/esri-compat/feature-filter.js +49 -0
- package/esri-compat/geojson-layer.d.ts +4 -2
- package/esri-compat/geojson-layer.d.ts.map +1 -1
- package/esri-compat/geojson-layer.js +4 -2
- package/esri-compat/identity-manager.js +2 -2
- package/esri-compat/imagery-layer.d.ts +2 -1
- package/esri-compat/imagery-layer.d.ts.map +1 -1
- package/esri-compat/imagery-layer.js +2 -1
- package/esri-compat/layer-list.d.ts +8 -1
- package/esri-compat/layer-list.d.ts.map +1 -1
- package/esri-compat/layer-list.js +11 -4
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +1 -1
- package/esri-compat/locator.d.ts +297 -0
- package/esri-compat/locator.d.ts.map +1 -0
- package/esri-compat/locator.js +579 -0
- package/esri-compat/map-image-layer.d.ts.map +1 -1
- package/esri-compat/map-view.d.ts.map +1 -1
- package/esri-compat/map-view.js +1 -1
- package/esri-compat/scene-view.d.ts.map +1 -1
- package/esri-compat/time-slider.d.ts +29 -0
- package/esri-compat/time-slider.d.ts.map +1 -1
- package/esri-compat/time-slider.js +117 -0
- package/esri-compat/wfs-layer.d.ts +2 -1
- package/esri-compat/wfs-layer.d.ts.map +1 -1
- package/esri-compat/wfs-layer.js +2 -1
- package/esri-compat/widget-host.d.ts +42 -6
- package/esri-compat/widget-host.d.ts.map +1 -1
- package/esri-compat/widget-host.js +99 -10
- package/generated-app/projection.d.ts.map +1 -1
- package/generated-app/runtime.d.ts.map +1 -1
- package/interactions/declarative-contract.d.ts +149 -0
- package/interactions/declarative-contract.d.ts.map +1 -0
- package/interactions/declarative-contract.js +293 -0
- package/interactions/declarative.d.ts +198 -0
- package/interactions/declarative.d.ts.map +1 -0
- package/interactions/declarative.js +470 -0
- package/interactions/feature-state.d.ts +7 -0
- package/interactions/feature-state.d.ts.map +1 -1
- package/interactions/feature-state.js +10 -2
- package/map/data-to-map-bridge.d.ts +1 -1
- package/map/data-to-map-bridge.d.ts.map +1 -1
- package/map/data-to-map-bridge.js +1 -2
- package/map/honua-map.d.ts.map +1 -1
- package/map/honua-map.js +1 -1
- package/map/index.d.ts +2 -0
- package/map/index.d.ts.map +1 -1
- package/map/index.js +2 -0
- package/map/maplibre-target.js +1 -1
- package/map/realtime-reconciliation-adapter.d.ts +98 -0
- package/map/realtime-reconciliation-adapter.d.ts.map +1 -0
- package/map/realtime-reconciliation-adapter.js +84 -0
- package/map/temporal-playback.d.ts +25 -0
- package/map/temporal-playback.d.ts.map +1 -1
- package/map/temporal-playback.js +29 -1
- package/operator/workspace/workspace.d.ts.map +1 -1
- package/operator/workspace/workspace.js +0 -2
- package/package.json +4 -3
- package/query-planner/canonical-filter.d.ts +30 -0
- package/query-planner/canonical-filter.d.ts.map +1 -0
- package/query-planner/canonical-filter.js +30 -0
- package/query-planner/columnar-plan.d.ts +63 -0
- package/query-planner/columnar-plan.d.ts.map +1 -0
- package/query-planner/columnar-plan.js +94 -0
- package/query-planner/diagnostics.d.ts +3 -3
- package/query-planner/diagnostics.d.ts.map +1 -1
- package/query-planner/diagnostics.js +17 -4
- package/query-planner/duckdb.d.ts.map +1 -1
- package/query-planner/duckdb.js +16 -2
- package/query-planner/execution-context.d.ts.map +1 -1
- package/query-planner/execution-context.js +3 -1
- package/query-planner/executor.d.ts.map +1 -1
- package/query-planner/executor.js +7 -1
- package/query-planner/geoservices.d.ts.map +1 -1
- package/query-planner/geoservices.js +24 -5
- package/query-planner/grpc.d.ts.map +1 -1
- package/query-planner/grpc.js +29 -5
- package/query-planner/index.d.ts +20 -5
- package/query-planner/index.d.ts.map +1 -1
- package/query-planner/index.js +16 -3
- package/query-planner/ir.d.ts +6 -1
- package/query-planner/ir.d.ts.map +1 -1
- package/query-planner/ir.js +63 -1
- package/query-planner/odata-protocol-module.d.ts +54 -0
- package/query-planner/odata-protocol-module.d.ts.map +1 -0
- package/query-planner/odata-protocol-module.js +199 -0
- package/query-planner/odata-v1.d.ts +23 -0
- package/query-planner/odata-v1.d.ts.map +1 -0
- package/query-planner/odata-v1.js +202 -0
- package/query-planner/odata.d.ts +0 -3
- package/query-planner/odata.d.ts.map +1 -1
- package/query-planner/odata.js +0 -143
- package/query-planner/ogc-features.d.ts.map +1 -1
- package/query-planner/ogc-features.js +23 -1
- package/query-planner/planner.d.ts +2 -2
- package/query-planner/planner.d.ts.map +1 -1
- package/query-planner/planner.js +146 -27
- package/query-planner/representation.d.ts +59 -0
- package/query-planner/representation.d.ts.map +1 -0
- package/query-planner/representation.js +140 -0
- package/query-planner/types.d.ts +153 -3
- package/query-planner/types.d.ts.map +1 -1
- package/query-planner/wfs-protocol-module.d.ts +57 -0
- package/query-planner/wfs-protocol-module.d.ts.map +1 -0
- package/query-planner/wfs-protocol-module.js +731 -0
- package/query-planner/wfs-v1.d.ts +41 -0
- package/query-planner/wfs-v1.d.ts.map +1 -0
- package/query-planner/wfs-v1.js +366 -0
- package/query-planner/wfs.d.ts +1 -3
- package/query-planner/wfs.d.ts.map +1 -1
- package/query-planner/wfs.js +1 -70
- package/realtime/checkpoint-store.d.ts +206 -0
- package/realtime/checkpoint-store.d.ts.map +1 -0
- package/realtime/checkpoint-store.js +504 -0
- package/realtime/honua-server.d.ts +8 -0
- package/realtime/honua-server.d.ts.map +1 -1
- package/realtime/honua-server.js +123 -14
- package/realtime/index.d.ts +4 -0
- package/realtime/index.d.ts.map +1 -1
- package/realtime/index.js +2 -0
- package/realtime/reconciliation.d.ts +245 -0
- package/realtime/reconciliation.d.ts.map +1 -0
- package/realtime/reconciliation.js +377 -0
- package/realtime/resumable-transport.d.ts.map +1 -1
- package/realtime/sse.d.ts.map +1 -1
- package/realtime/sse.js +7 -1
- package/realtime/websocket.d.ts.map +1 -1
- package/realtime/wire.d.ts +2 -1
- package/realtime/wire.d.ts.map +1 -1
- package/realtime/wire.js +24 -8
- package/replica-sync/errors.d.ts +19 -1
- package/replica-sync/errors.d.ts.map +1 -1
- package/replica-sync/errors.js +16 -0
- package/replica-sync/geoservices.d.ts +260 -0
- package/replica-sync/geoservices.d.ts.map +1 -0
- package/replica-sync/geoservices.js +1093 -0
- package/replica-sync/index.d.ts +5 -1
- package/replica-sync/index.d.ts.map +1 -1
- package/replica-sync/index.js +3 -1
- package/replica-sync/transport-conformance.d.ts +58 -0
- package/replica-sync/transport-conformance.d.ts.map +1 -0
- package/replica-sync/transport-conformance.js +265 -0
- package/replica-sync/types.d.ts +22 -0
- package/replica-sync/types.d.ts.map +1 -1
- package/runtime/index.d.ts +6 -2
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +3 -1
- package/runtime/load-package.d.ts +24 -0
- package/runtime/load-package.d.ts.map +1 -1
- package/runtime/load-package.js +45 -1
- package/runtime/maplibre-renderer.d.ts +11 -0
- package/runtime/maplibre-renderer.d.ts.map +1 -1
- package/runtime/maplibre-renderer.js +32 -7
- package/runtime/offline-region-protocol.d.ts +73 -0
- package/runtime/offline-region-protocol.d.ts.map +1 -0
- package/runtime/offline-region-protocol.js +63 -0
- package/runtime/offline-region-style.d.ts +78 -0
- package/runtime/offline-region-style.d.ts.map +1 -0
- package/runtime/offline-region-style.js +147 -0
- package/runtime/pmtiles-protocol.d.ts +7 -8
- package/runtime/pmtiles-protocol.d.ts.map +1 -1
- package/runtime/pmtiles-protocol.js +19 -66
- package/runtime/protocol-registry.d.ts +55 -0
- package/runtime/protocol-registry.d.ts.map +1 -0
- package/runtime/protocol-registry.js +103 -0
- package/runtime/runtime.d.ts +2 -0
- package/runtime/runtime.d.ts.map +1 -1
- package/runtime/runtime.js +6 -1
- package/runtime/style-compose.d.ts.map +1 -1
- package/runtime/style-compose.js +78 -9
- package/scene-workspace/analysis-widgets.d.ts +4 -2
- package/scene-workspace/analysis-widgets.d.ts.map +1 -1
- package/scene-workspace/analysis-widgets.js +4 -2
- package/scene-workspace/camera-correspondence.d.ts +151 -0
- package/scene-workspace/camera-correspondence.d.ts.map +1 -0
- package/scene-workspace/camera-correspondence.js +220 -0
- package/scene-workspace/cesium-adapter.d.ts +230 -29
- package/scene-workspace/cesium-adapter.d.ts.map +1 -1
- package/scene-workspace/cesium-adapter.js +741 -56
- package/scene-workspace/cesium-mount.d.ts +205 -0
- package/scene-workspace/cesium-mount.d.ts.map +1 -0
- package/scene-workspace/cesium-mount.js +392 -0
- package/scene-workspace/cesium-scene-owner.d.ts +160 -0
- package/scene-workspace/cesium-scene-owner.d.ts.map +1 -0
- package/scene-workspace/cesium-scene-owner.js +205 -0
- package/scene-workspace/cesium-state-sync.d.ts +101 -0
- package/scene-workspace/cesium-state-sync.d.ts.map +1 -0
- package/scene-workspace/cesium-state-sync.js +432 -0
- package/scene-workspace/cesium-time.d.ts +346 -0
- package/scene-workspace/cesium-time.d.ts.map +1 -0
- package/scene-workspace/cesium-time.js +403 -0
- package/scene-workspace/index.d.ts +42 -10
- package/scene-workspace/index.d.ts.map +1 -1
- package/scene-workspace/index.js +32 -7
- package/scene-workspace/maplibre-state-sync.d.ts +112 -0
- package/scene-workspace/maplibre-state-sync.d.ts.map +1 -0
- package/scene-workspace/maplibre-state-sync.js +400 -0
- package/scene-workspace/primitives.d.ts +237 -3
- package/scene-workspace/primitives.d.ts.map +1 -1
- package/scene-workspace/primitives.js +1087 -17
- package/scene-workspace/scene-discovery.d.ts +5 -2
- package/scene-workspace/scene-discovery.d.ts.map +1 -1
- package/scene-workspace/scene-discovery.js +5 -2
- package/scene-workspace/scene-view.d.ts +5 -2
- package/scene-workspace/scene-view.d.ts.map +1 -1
- package/scene-workspace/scene-view.js +5 -2
- package/scene-workspace/source-to-cesium.d.ts +141 -8
- package/scene-workspace/source-to-cesium.d.ts.map +1 -1
- package/scene-workspace/source-to-cesium.js +497 -72
- package/scene-workspace/state-sync-port-kit.d.ts +156 -0
- package/scene-workspace/state-sync-port-kit.d.ts.map +1 -0
- package/scene-workspace/state-sync-port-kit.js +319 -0
- package/scene-workspace/state-sync.d.ts +34 -1
- package/scene-workspace/state-sync.d.ts.map +1 -1
- package/scene-workspace/state-sync.js +48 -0
- package/scene-workspace/types.d.ts +8 -0
- package/scene-workspace/types.d.ts.map +1 -1
- package/scene-workspace/types.js +2 -0
- package/scene-workspace/workspace.d.ts +12 -1
- package/scene-workspace/workspace.d.ts.map +1 -1
- package/scene-workspace/workspace.js +13 -0
- package/studio/index.d.ts +24 -7
- package/studio/index.d.ts.map +1 -1
- package/studio/index.js +21 -7
- package/studio/lifecycle-client.d.ts +164 -0
- package/studio/lifecycle-client.d.ts.map +1 -0
- package/studio/lifecycle-client.js +299 -0
- package/studio/lifecycle-errors.d.ts +91 -0
- package/studio/lifecycle-errors.d.ts.map +1 -0
- package/studio/lifecycle-errors.js +77 -0
- package/studio/lifecycle-types.d.ts +321 -0
- package/studio/lifecycle-types.d.ts.map +1 -0
- package/studio/lifecycle-types.js +22 -0
- package/web-components/controller.d.ts.map +1 -1
- package/web-components/csp-styles.d.ts +6 -0
- package/web-components/csp-styles.d.ts.map +1 -0
- package/web-components/csp-styles.js +53 -0
- package/web-components/elements.d.ts +158 -2
- package/web-components/elements.d.ts.map +1 -1
- package/web-components/elements.js +1302 -215
- package/web-components/export-redaction.d.ts +252 -0
- package/web-components/export-redaction.d.ts.map +1 -0
- package/web-components/export-redaction.js +588 -0
- package/web-components/export.d.ts +417 -0
- package/web-components/export.d.ts.map +1 -0
- package/web-components/export.js +719 -0
- package/web-components/feature-editor-model.d.ts +265 -0
- package/web-components/feature-editor-model.d.ts.map +1 -0
- package/web-components/feature-editor-model.js +438 -0
- package/web-components/feature-editor-sketch.d.ts +125 -0
- package/web-components/feature-editor-sketch.d.ts.map +1 -0
- package/web-components/feature-editor-sketch.js +194 -0
- package/web-components/feature-editor-workflow.d.ts +286 -0
- package/web-components/feature-editor-workflow.d.ts.map +1 -0
- package/web-components/feature-editor-workflow.js +889 -0
- package/web-components/feature-editor.d.ts +83 -0
- package/web-components/feature-editor.d.ts.map +1 -0
- package/web-components/feature-editor.js +829 -0
- package/web-components/feature-table-engine.d.ts +465 -0
- package/web-components/feature-table-engine.d.ts.map +1 -0
- package/web-components/feature-table-engine.js +1360 -0
- package/web-components/feature-table-view.d.ts +95 -0
- package/web-components/feature-table-view.d.ts.map +1 -0
- package/web-components/feature-table-view.js +343 -0
- package/web-components/index.d.ts +34 -3
- package/web-components/index.d.ts.map +1 -1
- package/web-components/index.js +35 -2
- package/web-components/maplibre-renderer.d.ts.map +1 -1
- package/web-components/maplibre-renderer.js +13 -4
- package/web-components/measurement.d.ts +3 -1
- package/web-components/measurement.d.ts.map +1 -1
- package/web-components/measurement.js +62 -18
- package/web-components/time-slider.d.ts +122 -0
- package/web-components/time-slider.d.ts.map +1 -0
- package/web-components/time-slider.js +740 -0
- package/web-components/types.d.ts +310 -0
- package/web-components/types.d.ts.map +1 -1
- package/webmap/convert-label.js +0 -1
- package/webmap/convert-symbol.d.ts.map +1 -1
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded mount lifecycle for Cesium scene primitives.
|
|
3
|
+
*
|
|
4
|
+
* `applyCesiumScenePrimitives()` is a one-shot projection: it hands back the
|
|
5
|
+
* layer handles it created and forgets them. That is fine for a script and wrong
|
|
6
|
+
* for an application, which must be able to revise the plan, cancel a mount that
|
|
7
|
+
* is still loading, and prove on unmount that nothing survived.
|
|
8
|
+
*
|
|
9
|
+
* {@link mountScenePrimitivesToCesium} adds the missing half — one handle that
|
|
10
|
+
* owns every adapter-created renderer resource for as long as the plan is live:
|
|
11
|
+
*
|
|
12
|
+
* - **Bounded.** A mount owns at most {@link MountScenePrimitivesToCesiumOptions.maxLayers}
|
|
13
|
+
* layer handles. A plan that would exceed the ceiling is rejected before the
|
|
14
|
+
* Cesium peer is even loaded, so the ceiling is a real admission gate rather
|
|
15
|
+
* than a post-hoc count.
|
|
16
|
+
* - **Diffed.** Re-applying a revised plan reuses every primitive whose identity
|
|
17
|
+
* and configuration are unchanged and disposes exactly the ones that left.
|
|
18
|
+
* - **Cancellation-safe.** An `AbortSignal` — the caller's, or the mount's own,
|
|
19
|
+
* fired by `dispose()` — unwinds an in-flight application through the adapter's
|
|
20
|
+
* transactional rollback, so an abandoned mount attaches nothing.
|
|
21
|
+
* - **Provably released.** `dispose()` is idempotent and releases every handle
|
|
22
|
+
* the mount owns exactly once, including after a partially failed application.
|
|
23
|
+
*
|
|
24
|
+
* Diagnostics stay plan-scoped: every application re-diagnoses the whole plan
|
|
25
|
+
* against {@link CESIUM_SCENE_CAPABILITIES}, so a reused primitive still reports
|
|
26
|
+
* its current spatial-reference, terrain, and model findings. The mount adds one
|
|
27
|
+
* lifecycle diagnostic per application describing what it created, reused, and
|
|
28
|
+
* disposed. Plan findings say whether a binding *can* render correctly; mount
|
|
29
|
+
* findings say what the renderer currently owns.
|
|
30
|
+
*
|
|
31
|
+
* Revisions additionally name what they had to cross. Every binding in a
|
|
32
|
+
* revision gets a {@link SceneRebuildBoundaryReport}, and each crossing that was
|
|
33
|
+
* *not* incremental also emits a `scene-mount-rebuild-boundary` diagnostic. A
|
|
34
|
+
* realtime data delta therefore reads as "this binding was rebuilt, for this
|
|
35
|
+
* reason, while these were reused", and a pure time advance reads as a revision
|
|
36
|
+
* with no crossings at all — application time lives in the workspace state, not
|
|
37
|
+
* in the plan, so it is outside the fingerprint the diff runs on.
|
|
38
|
+
*
|
|
39
|
+
* @beta Part of the beta `@honua/app-platform/scene-workspace` surface: the
|
|
40
|
+
* mount handle's shape, its idempotent `dispose()`, and the layer ceiling's
|
|
41
|
+
* fail-closed admission behavior hold through 0.1.x, and mount diagnostic
|
|
42
|
+
* codes grow additively. See the surface tiers table in
|
|
43
|
+
* `docs/standalone-capability-matrix.md`.
|
|
44
|
+
* @module
|
|
45
|
+
*/
|
|
46
|
+
import { type CesiumLayerHandle, type CesiumSceneRuntimeTarget } from "./cesium-adapter.js";
|
|
47
|
+
import { type SceneRebuildBoundaryReport } from "./cesium-time.js";
|
|
48
|
+
import { type ScenePrimitiveApplyResult, type ScenePrimitiveDiagnostic, type SceneRuntimePrimitive } from "./primitives.js";
|
|
49
|
+
import type { SceneWorkspaceState } from "./types.js";
|
|
50
|
+
/**
|
|
51
|
+
* Default ceiling on the number of live layer handles one mount may own.
|
|
52
|
+
*
|
|
53
|
+
* Terrain, imagery, tilesets, and models each pin GPU and worker resources for
|
|
54
|
+
* as long as they are attached, so an unbounded plan is an unbounded leak. Sixty
|
|
55
|
+
* four is generous for a hand-authored or server-published scene and small
|
|
56
|
+
* enough that a runaway generated plan fails closed instead of exhausting the
|
|
57
|
+
* renderer. Raise it deliberately with
|
|
58
|
+
* {@link MountScenePrimitivesToCesiumOptions.maxLayers}.
|
|
59
|
+
*/
|
|
60
|
+
export declare const DEFAULT_SCENE_MOUNT_LAYER_LIMIT = 64;
|
|
61
|
+
/**
|
|
62
|
+
* Failure codes raised by the scene mount lifecycle. Each one is a fail-closed
|
|
63
|
+
* refusal, never a partially applied plan.
|
|
64
|
+
*/
|
|
65
|
+
export type CesiumSceneMountErrorCode = "disposed" | "invalid-option" | "layer-limit-exceeded";
|
|
66
|
+
/**
|
|
67
|
+
* A lifecycle refusal from {@link mountScenePrimitivesToCesium} or
|
|
68
|
+
* {@link MountedCesiumScenePrimitives.apply}. Renderer failures surfacing from
|
|
69
|
+
* Cesium itself keep their own error types; this one is raised only by the
|
|
70
|
+
* mount's own contract.
|
|
71
|
+
*/
|
|
72
|
+
export declare class HonuaCesiumSceneMountError extends Error {
|
|
73
|
+
readonly code: CesiumSceneMountErrorCode;
|
|
74
|
+
readonly detail?: Readonly<Record<string, unknown>> | undefined;
|
|
75
|
+
constructor(code: CesiumSceneMountErrorCode, message: string, detail?: Readonly<Record<string, unknown>> | undefined, options?: ErrorOptions);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Lifecycle state of a scene mount.
|
|
79
|
+
*
|
|
80
|
+
* `disposing` is reachable in two ways: transiently, while `dispose()` runs, and
|
|
81
|
+
* durably, when a handle refused to release. The second case keeps the mount
|
|
82
|
+
* retryable — `dispose()` may be called again and will retry only what is still
|
|
83
|
+
* owned — while permanently refusing new applications.
|
|
84
|
+
*/
|
|
85
|
+
export type CesiumSceneMountState = "ready" | "applying" | "disposing" | "disposed";
|
|
86
|
+
/** Options for {@link mountScenePrimitivesToCesium}. */
|
|
87
|
+
export interface MountScenePrimitivesToCesiumOptions {
|
|
88
|
+
/**
|
|
89
|
+
* Cancels the initial application. Aborting before or during materialization
|
|
90
|
+
* leaves the scene untouched, releases anything already attached, and rejects
|
|
91
|
+
* the mount promise with the signal's reason.
|
|
92
|
+
*/
|
|
93
|
+
readonly signal?: AbortSignal;
|
|
94
|
+
/**
|
|
95
|
+
* Ceiling on the live layer handles this mount may own. Defaults to
|
|
96
|
+
* {@link DEFAULT_SCENE_MOUNT_LAYER_LIMIT}. Must be a positive integer.
|
|
97
|
+
*/
|
|
98
|
+
readonly maxLayers?: number;
|
|
99
|
+
/**
|
|
100
|
+
* Workspace state carried alongside the plan, mirroring the adapter's `apply`.
|
|
101
|
+
* Its `timeline` slice drives the target's clock (when the host bound one) and
|
|
102
|
+
* its `realtime` slice is recorded as the application's provenance.
|
|
103
|
+
*/
|
|
104
|
+
readonly state?: SceneWorkspaceState;
|
|
105
|
+
}
|
|
106
|
+
/** Options for {@link MountedCesiumScenePrimitives.apply}. */
|
|
107
|
+
export interface ApplyMountedScenePrimitivesOptions {
|
|
108
|
+
/** Cancels this application only; the mount itself stays usable. */
|
|
109
|
+
readonly signal?: AbortSignal;
|
|
110
|
+
/**
|
|
111
|
+
* Workspace state carried alongside the plan, mirroring the adapter's `apply`.
|
|
112
|
+
* Its `timeline` slice drives the target's clock (when the host bound one) and
|
|
113
|
+
* its `realtime` slice is recorded as the application's provenance.
|
|
114
|
+
*/
|
|
115
|
+
readonly state?: SceneWorkspaceState;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The result of one application through a mount: the adapter's own apply result
|
|
119
|
+
* plus the diff that produced it.
|
|
120
|
+
*/
|
|
121
|
+
export interface MountedScenePrimitiveApplyResult extends ScenePrimitiveApplyResult {
|
|
122
|
+
/** Live layer handles keyed by primitive id, reused and newly created alike. */
|
|
123
|
+
readonly layers: ReadonlyMap<string, CesiumLayerHandle>;
|
|
124
|
+
/** 1 for the initial application, incremented for every revision. */
|
|
125
|
+
readonly revision: number;
|
|
126
|
+
/** Ids whose renderer resource was constructed by this application. */
|
|
127
|
+
readonly created: readonly string[];
|
|
128
|
+
/** Ids whose renderer resource was carried forward untouched. */
|
|
129
|
+
readonly reused: readonly string[];
|
|
130
|
+
/** Ids whose renderer resource was released because the primitive left or changed. */
|
|
131
|
+
readonly disposed: readonly string[];
|
|
132
|
+
/**
|
|
133
|
+
* One entry per binding involved in this update, naming the rebuild boundary
|
|
134
|
+
* it crossed — `"none"` for the bindings applied in place. This is the single
|
|
135
|
+
* list that answers "which parts of this update were incremental, and which
|
|
136
|
+
* forced a rebuild".
|
|
137
|
+
*
|
|
138
|
+
* Empty on the initial application: with no previously mounted plan to
|
|
139
|
+
* compare against, every binding is a construction rather than a crossing,
|
|
140
|
+
* and `created` already reports that.
|
|
141
|
+
*/
|
|
142
|
+
readonly rebuildBoundaries: readonly SceneRebuildBoundaryReport[];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* One mount of a scene plan against a live Cesium target.
|
|
146
|
+
*
|
|
147
|
+
* The mount owns every layer handle it created. Callers hold the mount, not the
|
|
148
|
+
* handles: a revision goes through {@link apply} and teardown goes through
|
|
149
|
+
* {@link dispose}, so there is never a set of handles the caller must remember
|
|
150
|
+
* to release separately.
|
|
151
|
+
*/
|
|
152
|
+
export interface MountedCesiumScenePrimitives {
|
|
153
|
+
readonly renderer: "cesium";
|
|
154
|
+
/** Lifecycle state. See {@link CesiumSceneMountState}. */
|
|
155
|
+
readonly state: CesiumSceneMountState;
|
|
156
|
+
/** Status of the most recent application, summarized from its diagnostics. */
|
|
157
|
+
readonly status: ScenePrimitiveApplyResult["status"];
|
|
158
|
+
/** Diagnostics from the most recent application: plan findings plus the lifecycle finding. */
|
|
159
|
+
readonly diagnostics: readonly ScenePrimitiveDiagnostic[];
|
|
160
|
+
/** Live layer handles keyed by primitive id. Empty once disposed. */
|
|
161
|
+
readonly layers: ReadonlyMap<string, CesiumLayerHandle>;
|
|
162
|
+
/** Rebuild boundaries crossed by the most recent application. */
|
|
163
|
+
readonly rebuildBoundaries: readonly SceneRebuildBoundaryReport[];
|
|
164
|
+
/** The ceiling this mount was created with. */
|
|
165
|
+
readonly layerLimit: number;
|
|
166
|
+
/** 1 after the initial application, incremented for every revision. */
|
|
167
|
+
readonly revision: number;
|
|
168
|
+
/**
|
|
169
|
+
* Apply a revised plan through this mount. Primitives whose identity and
|
|
170
|
+
* configuration are unchanged are reused untouched; primitives that left the
|
|
171
|
+
* plan — or whose configuration changed — are disposed once the revision has
|
|
172
|
+
* landed. A failure rolls the scene back to the previously applied plan.
|
|
173
|
+
*
|
|
174
|
+
* Applications are serialized: a second call queues behind the first rather
|
|
175
|
+
* than interleaving scene mutations.
|
|
176
|
+
*
|
|
177
|
+
* Re-applying the *same* plan with a moved `options.state.timeline` is the
|
|
178
|
+
* incremental time path: nothing is rebuilt, every handle is carried forward
|
|
179
|
+
* by identity, and only the bound clock changes.
|
|
180
|
+
*/
|
|
181
|
+
apply(primitives: readonly SceneRuntimePrimitive[], options?: ApplyMountedScenePrimitivesOptions): Promise<MountedScenePrimitiveApplyResult>;
|
|
182
|
+
/**
|
|
183
|
+
* Release every resource this mount owns. Idempotent: the second call is a
|
|
184
|
+
* no-op. Cancels any in-flight application first, so a mount disposed mid-load
|
|
185
|
+
* cannot be completed behind the caller's back.
|
|
186
|
+
*
|
|
187
|
+
* If a handle refuses to release, the failures are aggregated and thrown, the
|
|
188
|
+
* mount stays in `disposing`, and a later `dispose()` retries only what is
|
|
189
|
+
* still owned.
|
|
190
|
+
*/
|
|
191
|
+
dispose(): void;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Mount a scene plan against a live Cesium target and return the handle that
|
|
195
|
+
* owns it.
|
|
196
|
+
*
|
|
197
|
+
* The initial plan is applied before the promise resolves, so a resolved mount
|
|
198
|
+
* is a mounted scene. A rejection means nothing was left attached: the adapter's
|
|
199
|
+
* transactional rollback has already run.
|
|
200
|
+
*
|
|
201
|
+
* @param target Live Cesium `Viewer`/`Scene` surface (a `camera`, optionally a `scene`).
|
|
202
|
+
* @param primitives The accepted scene plan.
|
|
203
|
+
*/
|
|
204
|
+
export declare function mountScenePrimitivesToCesium(target: CesiumSceneRuntimeTarget, primitives: readonly SceneRuntimePrimitive[], options?: MountScenePrimitivesToCesiumOptions): Promise<MountedCesiumScenePrimitives>;
|
|
205
|
+
//# sourceMappingURL=cesium-mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cesium-mount.d.ts","sourceRoot":"","sources":["../../../src/scene-workspace/cesium-mount.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded mount lifecycle for Cesium scene primitives.
|
|
3
|
+
*
|
|
4
|
+
* `applyCesiumScenePrimitives()` is a one-shot projection: it hands back the
|
|
5
|
+
* layer handles it created and forgets them. That is fine for a script and wrong
|
|
6
|
+
* for an application, which must be able to revise the plan, cancel a mount that
|
|
7
|
+
* is still loading, and prove on unmount that nothing survived.
|
|
8
|
+
*
|
|
9
|
+
* {@link mountScenePrimitivesToCesium} adds the missing half — one handle that
|
|
10
|
+
* owns every adapter-created renderer resource for as long as the plan is live:
|
|
11
|
+
*
|
|
12
|
+
* - **Bounded.** A mount owns at most {@link MountScenePrimitivesToCesiumOptions.maxLayers}
|
|
13
|
+
* layer handles. A plan that would exceed the ceiling is rejected before the
|
|
14
|
+
* Cesium peer is even loaded, so the ceiling is a real admission gate rather
|
|
15
|
+
* than a post-hoc count.
|
|
16
|
+
* - **Diffed.** Re-applying a revised plan reuses every primitive whose identity
|
|
17
|
+
* and configuration are unchanged and disposes exactly the ones that left.
|
|
18
|
+
* - **Cancellation-safe.** An `AbortSignal` — the caller's, or the mount's own,
|
|
19
|
+
* fired by `dispose()` — unwinds an in-flight application through the adapter's
|
|
20
|
+
* transactional rollback, so an abandoned mount attaches nothing.
|
|
21
|
+
* - **Provably released.** `dispose()` is idempotent and releases every handle
|
|
22
|
+
* the mount owns exactly once, including after a partially failed application.
|
|
23
|
+
*
|
|
24
|
+
* Diagnostics stay plan-scoped: every application re-diagnoses the whole plan
|
|
25
|
+
* against {@link CESIUM_SCENE_CAPABILITIES}, so a reused primitive still reports
|
|
26
|
+
* its current spatial-reference, terrain, and model findings. The mount adds one
|
|
27
|
+
* lifecycle diagnostic per application describing what it created, reused, and
|
|
28
|
+
* disposed. Plan findings say whether a binding *can* render correctly; mount
|
|
29
|
+
* findings say what the renderer currently owns.
|
|
30
|
+
*
|
|
31
|
+
* Revisions additionally name what they had to cross. Every binding in a
|
|
32
|
+
* revision gets a {@link SceneRebuildBoundaryReport}, and each crossing that was
|
|
33
|
+
* *not* incremental also emits a `scene-mount-rebuild-boundary` diagnostic. A
|
|
34
|
+
* realtime data delta therefore reads as "this binding was rebuilt, for this
|
|
35
|
+
* reason, while these were reused", and a pure time advance reads as a revision
|
|
36
|
+
* with no crossings at all — application time lives in the workspace state, not
|
|
37
|
+
* in the plan, so it is outside the fingerprint the diff runs on.
|
|
38
|
+
*
|
|
39
|
+
* @beta Part of the beta `@honua/app-platform/scene-workspace` surface: the
|
|
40
|
+
* mount handle's shape, its idempotent `dispose()`, and the layer ceiling's
|
|
41
|
+
* fail-closed admission behavior hold through 0.1.x, and mount diagnostic
|
|
42
|
+
* codes grow additively. See the surface tiers table in
|
|
43
|
+
* `docs/standalone-capability-matrix.md`.
|
|
44
|
+
* @module
|
|
45
|
+
*/
|
|
46
|
+
import { CESIUM_SCENE_CAPABILITIES, applyCesiumScenePrimitivesInternal, scenePrimitiveFingerprint, scenePrimitiveMountKey, } from "./cesium-adapter.js";
|
|
47
|
+
import { sceneRebuildBoundaryReport, } from "./cesium-time.js";
|
|
48
|
+
import { summarizeDiagnosticStatus, } from "./primitives.js";
|
|
49
|
+
/**
|
|
50
|
+
* Default ceiling on the number of live layer handles one mount may own.
|
|
51
|
+
*
|
|
52
|
+
* Terrain, imagery, tilesets, and models each pin GPU and worker resources for
|
|
53
|
+
* as long as they are attached, so an unbounded plan is an unbounded leak. Sixty
|
|
54
|
+
* four is generous for a hand-authored or server-published scene and small
|
|
55
|
+
* enough that a runaway generated plan fails closed instead of exhausting the
|
|
56
|
+
* renderer. Raise it deliberately with
|
|
57
|
+
* {@link MountScenePrimitivesToCesiumOptions.maxLayers}.
|
|
58
|
+
*/
|
|
59
|
+
export const DEFAULT_SCENE_MOUNT_LAYER_LIMIT = 64;
|
|
60
|
+
/**
|
|
61
|
+
* A lifecycle refusal from {@link mountScenePrimitivesToCesium} or
|
|
62
|
+
* {@link MountedCesiumScenePrimitives.apply}. Renderer failures surfacing from
|
|
63
|
+
* Cesium itself keep their own error types; this one is raised only by the
|
|
64
|
+
* mount's own contract.
|
|
65
|
+
*/
|
|
66
|
+
export class HonuaCesiumSceneMountError extends Error {
|
|
67
|
+
code;
|
|
68
|
+
detail;
|
|
69
|
+
constructor(code, message, detail, options) {
|
|
70
|
+
super(message, options);
|
|
71
|
+
this.code = code;
|
|
72
|
+
this.detail = detail;
|
|
73
|
+
this.name = "HonuaCesiumSceneMountError";
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Mount a scene plan against a live Cesium target and return the handle that
|
|
78
|
+
* owns it.
|
|
79
|
+
*
|
|
80
|
+
* The initial plan is applied before the promise resolves, so a resolved mount
|
|
81
|
+
* is a mounted scene. A rejection means nothing was left attached: the adapter's
|
|
82
|
+
* transactional rollback has already run.
|
|
83
|
+
*
|
|
84
|
+
* @param target Live Cesium `Viewer`/`Scene` surface (a `camera`, optionally a `scene`).
|
|
85
|
+
* @param primitives The accepted scene plan.
|
|
86
|
+
*/
|
|
87
|
+
export async function mountScenePrimitivesToCesium(target, primitives, options = {}) {
|
|
88
|
+
const layerLimit = resolveLayerLimit(options.maxLayers);
|
|
89
|
+
const lifecycle = new AbortController();
|
|
90
|
+
let entries = new Map();
|
|
91
|
+
let orphans = [];
|
|
92
|
+
let diagnostics = [];
|
|
93
|
+
let rebuildBoundaries = Object.freeze([]);
|
|
94
|
+
let status = "supported";
|
|
95
|
+
let state = "ready";
|
|
96
|
+
let revision = 0;
|
|
97
|
+
let applyTail = Promise.resolve();
|
|
98
|
+
let disposeActive = false;
|
|
99
|
+
const runApply = async (plan, applyOptions) => {
|
|
100
|
+
if (state === "disposing" || state === "disposed") {
|
|
101
|
+
throw new HonuaCesiumSceneMountError("disposed", "Cannot apply a plan through a disposed Cesium scene mount.");
|
|
102
|
+
}
|
|
103
|
+
assertWithinLayerLimit(plan, layerLimit);
|
|
104
|
+
const signal = combineSignals([lifecycle.signal, applyOptions.signal]);
|
|
105
|
+
signal.throwIfAborted();
|
|
106
|
+
// Identity + configuration diff against what is already mounted. A primitive
|
|
107
|
+
// with no fingerprint is treated as changed, never as unchanged.
|
|
108
|
+
//
|
|
109
|
+
// The same walk names the rebuild boundary each binding crosses, so the
|
|
110
|
+
// reuse decision and the diagnostic that explains it can never disagree.
|
|
111
|
+
// Boundaries are only meaningful against a previously mounted plan, so the
|
|
112
|
+
// initial application reports none.
|
|
113
|
+
const isRevision = revision > 0;
|
|
114
|
+
const boundaries = [];
|
|
115
|
+
const reuse = new Map();
|
|
116
|
+
const planEntries = [];
|
|
117
|
+
for (const primitive of plan) {
|
|
118
|
+
const key = scenePrimitiveMountKey(primitive);
|
|
119
|
+
const fingerprint = scenePrimitiveFingerprint(primitive);
|
|
120
|
+
const previous = entries.get(key);
|
|
121
|
+
const unchanged = previous !== undefined && fingerprint !== undefined && previous.fingerprint === fingerprint;
|
|
122
|
+
if (unchanged)
|
|
123
|
+
reuse.set(key, previous.handle);
|
|
124
|
+
if (isRevision) {
|
|
125
|
+
boundaries.push(sceneRebuildBoundaryReport(primitive.id, primitive.kind, boundaryFor(previous, fingerprint)));
|
|
126
|
+
}
|
|
127
|
+
planEntries.push({ key, id: primitive.id, kind: primitive.kind, fingerprint, handle: undefined });
|
|
128
|
+
}
|
|
129
|
+
state = "applying";
|
|
130
|
+
let application;
|
|
131
|
+
try {
|
|
132
|
+
application = await applyCesiumScenePrimitivesInternal(target, plan, {
|
|
133
|
+
signal,
|
|
134
|
+
reuse,
|
|
135
|
+
...(applyOptions.state ? { state: applyOptions.state } : {}),
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
finally {
|
|
139
|
+
if (state === "applying")
|
|
140
|
+
state = "ready";
|
|
141
|
+
}
|
|
142
|
+
if (lifecycle.signal.aborted) {
|
|
143
|
+
// Disposal won the race with a materialization that had no checkpoint left
|
|
144
|
+
// to hit. Release what this application built rather than committing it
|
|
145
|
+
// into a mount the host has already torn down.
|
|
146
|
+
releaseHandles(collectCreatedHandles(application.mounted, reuse));
|
|
147
|
+
throw lifecycle.signal.reason;
|
|
148
|
+
}
|
|
149
|
+
// Only now that the revision has landed is it safe to release what it
|
|
150
|
+
// displaced. Disposing earlier would make a mid-application failure
|
|
151
|
+
// unrecoverable.
|
|
152
|
+
const nextEntries = new Map();
|
|
153
|
+
for (const entry of planEntries) {
|
|
154
|
+
nextEntries.set(entry.key, { ...entry, handle: application.mounted.get(entry.key) });
|
|
155
|
+
}
|
|
156
|
+
const disposed = [];
|
|
157
|
+
const disposalFailures = [];
|
|
158
|
+
for (const entry of [...entries.values()].reverse()) {
|
|
159
|
+
if (reuse.has(entry.key) || !entry.handle)
|
|
160
|
+
continue;
|
|
161
|
+
try {
|
|
162
|
+
entry.handle.remove();
|
|
163
|
+
disposed.push(entry.id);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
disposalFailures.push(error);
|
|
167
|
+
// Still owned, so still this mount's problem: `dispose()` retries it.
|
|
168
|
+
orphans.push(entry.handle);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
// A binding that left the plan entirely crosses its own boundary; it is not
|
|
172
|
+
// in `plan`, so the diff walk above could not have reported it.
|
|
173
|
+
if (isRevision) {
|
|
174
|
+
for (const entry of entries.values()) {
|
|
175
|
+
if (nextEntries.has(entry.key))
|
|
176
|
+
continue;
|
|
177
|
+
boundaries.push(sceneRebuildBoundaryReport(entry.id, entry.kind, "plan-membership"));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
entries = nextEntries;
|
|
181
|
+
revision += 1;
|
|
182
|
+
rebuildBoundaries = Object.freeze([...boundaries]);
|
|
183
|
+
const crossed = rebuildBoundaries.filter((report) => !report.incremental);
|
|
184
|
+
const lifecycleDiagnostics = [
|
|
185
|
+
appliedDiagnostic(revision, application.created, application.reused, disposed, layerLimit, entries.size, applyOptions.state?.realtime, application.time.applied),
|
|
186
|
+
...crossed.map((report) => rebuildBoundaryDiagnostic(revision, report)),
|
|
187
|
+
...(disposalFailures.length > 0 ? [disposalIncompleteDiagnostic(disposalFailures)] : []),
|
|
188
|
+
];
|
|
189
|
+
diagnostics = Object.freeze([...application.diagnostics, ...lifecycleDiagnostics]);
|
|
190
|
+
status = summarizeDiagnosticStatus(diagnostics);
|
|
191
|
+
return {
|
|
192
|
+
status,
|
|
193
|
+
diagnostics,
|
|
194
|
+
layers: application.layers,
|
|
195
|
+
revision,
|
|
196
|
+
created: Object.freeze([...application.created]),
|
|
197
|
+
reused: Object.freeze([...application.reused]),
|
|
198
|
+
disposed: Object.freeze(disposed),
|
|
199
|
+
rebuildBoundaries,
|
|
200
|
+
};
|
|
201
|
+
};
|
|
202
|
+
const enqueueApply = (plan, applyOptions) => {
|
|
203
|
+
const value = applyTail.then(() => runApply(plan, applyOptions));
|
|
204
|
+
applyTail = value.then(() => undefined, () => undefined);
|
|
205
|
+
return value;
|
|
206
|
+
};
|
|
207
|
+
await runApply(primitives, {
|
|
208
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
209
|
+
...(options.state ? { state: options.state } : {}),
|
|
210
|
+
});
|
|
211
|
+
return {
|
|
212
|
+
renderer: "cesium",
|
|
213
|
+
get state() {
|
|
214
|
+
return state;
|
|
215
|
+
},
|
|
216
|
+
get status() {
|
|
217
|
+
return status;
|
|
218
|
+
},
|
|
219
|
+
get diagnostics() {
|
|
220
|
+
return diagnostics;
|
|
221
|
+
},
|
|
222
|
+
get rebuildBoundaries() {
|
|
223
|
+
return rebuildBoundaries;
|
|
224
|
+
},
|
|
225
|
+
get layers() {
|
|
226
|
+
const live = new Map();
|
|
227
|
+
for (const entry of entries.values())
|
|
228
|
+
if (entry.handle)
|
|
229
|
+
live.set(entry.id, entry.handle);
|
|
230
|
+
return live;
|
|
231
|
+
},
|
|
232
|
+
layerLimit,
|
|
233
|
+
get revision() {
|
|
234
|
+
return revision;
|
|
235
|
+
},
|
|
236
|
+
apply(plan, applyOptions = {}) {
|
|
237
|
+
return enqueueApply(plan, applyOptions);
|
|
238
|
+
},
|
|
239
|
+
dispose() {
|
|
240
|
+
if (state === "disposed" || disposeActive)
|
|
241
|
+
return;
|
|
242
|
+
disposeActive = true;
|
|
243
|
+
if (!lifecycle.signal.aborted) {
|
|
244
|
+
lifecycle.abort(new DOMException("Cesium scene mount disposed", "AbortError"));
|
|
245
|
+
}
|
|
246
|
+
state = "disposing";
|
|
247
|
+
try {
|
|
248
|
+
// Reverse construction order, orphaned handles from an earlier failure
|
|
249
|
+
// first, so a retry drains the backlog before the current plan.
|
|
250
|
+
const owned = [...entries.values()]
|
|
251
|
+
.reverse()
|
|
252
|
+
.map((entry) => entry.handle)
|
|
253
|
+
.filter((handle) => handle !== undefined);
|
|
254
|
+
const pending = [...orphans, ...owned];
|
|
255
|
+
orphans = [];
|
|
256
|
+
entries = new Map();
|
|
257
|
+
const failures = releaseHandles(pending);
|
|
258
|
+
orphans = failures.retained;
|
|
259
|
+
if (failures.errors.length > 0) {
|
|
260
|
+
throw new AggregateError(failures.errors, "Cesium scene mount disposal is incomplete and may be retried.");
|
|
261
|
+
}
|
|
262
|
+
state = "disposed";
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
disposeActive = false;
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function collectCreatedHandles(mountedHandles, reuse) {
|
|
271
|
+
const handles = [];
|
|
272
|
+
for (const [key, handle] of mountedHandles) {
|
|
273
|
+
if (handle && !reuse.has(key))
|
|
274
|
+
handles.push(handle);
|
|
275
|
+
}
|
|
276
|
+
return handles.reverse();
|
|
277
|
+
}
|
|
278
|
+
function releaseHandles(handles) {
|
|
279
|
+
const errors = [];
|
|
280
|
+
const retained = [];
|
|
281
|
+
for (const handle of handles) {
|
|
282
|
+
try {
|
|
283
|
+
handle.remove();
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
errors.push(error);
|
|
287
|
+
retained.push(handle);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
return { errors, retained };
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Reject an over-budget plan before the Cesium peer loads.
|
|
294
|
+
*
|
|
295
|
+
* The count is of primitives that would each materialize one adapter-owned layer
|
|
296
|
+
* handle. Camera, ground, extrusion, and scene-layer-metadata primitives own no
|
|
297
|
+
* renderer resource on this adapter and are not counted; an unsupported binding
|
|
298
|
+
* is counted, because refusing a plan must not depend on which of its bindings
|
|
299
|
+
* happen to be renderable today.
|
|
300
|
+
*/
|
|
301
|
+
function assertWithinLayerLimit(primitives, layerLimit) {
|
|
302
|
+
const layerCount = primitives.filter((primitive) => primitive.kind === "elevation-source" || primitive.kind === "imagery-layer" || primitive.kind === "model-layer").length;
|
|
303
|
+
if (layerCount > layerLimit) {
|
|
304
|
+
throw new HonuaCesiumSceneMountError("layer-limit-exceeded", `Scene plan declares ${layerCount} renderer layers, exceeding the mount ceiling ${layerLimit}.`, { layerCount, layerLimit });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
function resolveLayerLimit(maxLayers) {
|
|
308
|
+
if (maxLayers === undefined)
|
|
309
|
+
return DEFAULT_SCENE_MOUNT_LAYER_LIMIT;
|
|
310
|
+
if (!Number.isSafeInteger(maxLayers) || maxLayers <= 0) {
|
|
311
|
+
throw new HonuaCesiumSceneMountError("invalid-option", "maxLayers must be a positive integer.", { maxLayers });
|
|
312
|
+
}
|
|
313
|
+
return maxLayers;
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Classify one plan binding against what this mount already owns.
|
|
317
|
+
*
|
|
318
|
+
* The order matters: a binding the mount has never seen is an identity
|
|
319
|
+
* crossing regardless of whether it can be fingerprinted, and an
|
|
320
|
+
* unfingerprintable revision is called out as such rather than being reported as
|
|
321
|
+
* a configuration change nobody made.
|
|
322
|
+
*/
|
|
323
|
+
function boundaryFor(previous, fingerprint) {
|
|
324
|
+
if (previous === undefined)
|
|
325
|
+
return "primitive-identity";
|
|
326
|
+
if (fingerprint === undefined)
|
|
327
|
+
return "unfingerprintable";
|
|
328
|
+
return previous.fingerprint === fingerprint ? "none" : "primitive-configuration";
|
|
329
|
+
}
|
|
330
|
+
function appliedDiagnostic(revision, created, reused, disposed, layerLimit, mountedPrimitiveCount, realtime, timeApplied) {
|
|
331
|
+
return {
|
|
332
|
+
code: "scene-mount-applied",
|
|
333
|
+
severity: "info",
|
|
334
|
+
status: "supported",
|
|
335
|
+
renderer: CESIUM_SCENE_CAPABILITIES.renderer,
|
|
336
|
+
message: `Applied scene plan revision ${revision}: created ${created.length}, reused ${reused.length}, disposed ${disposed.length}.`,
|
|
337
|
+
context: {
|
|
338
|
+
revision,
|
|
339
|
+
created: [...created],
|
|
340
|
+
reused: [...reused],
|
|
341
|
+
disposed: [...disposed],
|
|
342
|
+
layerLimit,
|
|
343
|
+
mountedPrimitiveCount,
|
|
344
|
+
// Whether this revision also moved application time, so a time-only
|
|
345
|
+
// revision is legible as one rather than as an application that did
|
|
346
|
+
// nothing.
|
|
347
|
+
timeApplied,
|
|
348
|
+
// Provenance for a revision driven by a live feed: which feed state the
|
|
349
|
+
// delta arrived under, so a rebuild can be read against a reconnect or a
|
|
350
|
+
// stale window rather than in isolation.
|
|
351
|
+
...(realtime
|
|
352
|
+
? {
|
|
353
|
+
realtime: {
|
|
354
|
+
status: realtime.status,
|
|
355
|
+
...(realtime.cursor === undefined ? {} : { cursor: realtime.cursor }),
|
|
356
|
+
...(realtime.staleSince === undefined ? {} : { staleSince: realtime.staleSince }),
|
|
357
|
+
},
|
|
358
|
+
}
|
|
359
|
+
: {}),
|
|
360
|
+
},
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
function rebuildBoundaryDiagnostic(revision, report) {
|
|
364
|
+
return {
|
|
365
|
+
code: "scene-mount-rebuild-boundary",
|
|
366
|
+
severity: "info",
|
|
367
|
+
status: "supported",
|
|
368
|
+
primitiveId: report.id,
|
|
369
|
+
primitiveKind: report.kind,
|
|
370
|
+
renderer: CESIUM_SCENE_CAPABILITIES.renderer,
|
|
371
|
+
message: `Revision ${revision} could not update ${report.id} in place: ${report.reason}`,
|
|
372
|
+
context: { revision, rebuildBoundary: report.boundary, incremental: report.incremental },
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
function disposalIncompleteDiagnostic(failures) {
|
|
376
|
+
return {
|
|
377
|
+
code: "scene-mount-disposal-incomplete",
|
|
378
|
+
severity: "error",
|
|
379
|
+
status: "degraded",
|
|
380
|
+
renderer: CESIUM_SCENE_CAPABILITIES.renderer,
|
|
381
|
+
message: `${failures.length} displaced layer handle(s) refused to release; the revised plan is mounted and the handles remain owned.`,
|
|
382
|
+
fallback: "Call dispose() to retry releasing the retained handles.",
|
|
383
|
+
context: {
|
|
384
|
+
retainedHandleCount: failures.length,
|
|
385
|
+
failures: failures.map((failure) => (failure instanceof Error ? failure.message : String(failure))),
|
|
386
|
+
},
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function combineSignals(signals) {
|
|
390
|
+
const available = signals.filter((signal) => signal !== undefined);
|
|
391
|
+
return available.length === 1 ? available[0] : AbortSignal.any(available);
|
|
392
|
+
}
|