@honua/app-platform 0.0.20-alpha.0 → 0.1.1-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.
Files changed (381) hide show
  1. package/contract/discovery.d.ts +231 -0
  2. package/contract/discovery.d.ts.map +1 -0
  3. package/contract/discovery.js +554 -0
  4. package/contract/edit-sketch.d.ts +8 -0
  5. package/contract/edit-sketch.d.ts.map +1 -1
  6. package/contract/edit-sketch.js +15 -0
  7. package/contract/edit-snapping.d.ts +160 -0
  8. package/contract/edit-snapping.d.ts.map +1 -0
  9. package/contract/edit-snapping.js +675 -0
  10. package/contract/generated/projjson-v0.7-crs-validator.d.ts +35 -0
  11. package/contract/generated/projjson-v0.7-crs-validator.d.ts.map +1 -0
  12. package/contract/generated/projjson-v0.7-crs-validator.js +3941 -0
  13. package/contract/index.d.ts +11 -2
  14. package/contract/index.d.ts.map +1 -1
  15. package/contract/index.js +4 -1
  16. package/contract/pmtiles.d.ts +31 -0
  17. package/contract/pmtiles.d.ts.map +1 -1
  18. package/contract/pmtiles.js +60 -20
  19. package/contract/protocol-module.d.ts +70 -0
  20. package/contract/protocol-module.d.ts.map +1 -0
  21. package/contract/protocol-module.js +1 -0
  22. package/contract/schema-envelope.d.ts +26 -0
  23. package/contract/schema-envelope.d.ts.map +1 -0
  24. package/contract/schema-envelope.js +25 -0
  25. package/contract/schema.d.ts +582 -0
  26. package/contract/schema.d.ts.map +1 -0
  27. package/contract/schema.js +2483 -0
  28. package/contract/source-capability-support.d.ts +6 -0
  29. package/contract/source-capability-support.d.ts.map +1 -0
  30. package/contract/source-capability-support.js +154 -0
  31. package/contract/source.d.ts +35 -17
  32. package/contract/source.d.ts.map +1 -1
  33. package/contract/source.js +267 -71
  34. package/contract/types.d.ts +140 -4
  35. package/contract/types.d.ts.map +1 -1
  36. package/contract/types.js +6 -14
  37. package/core/bounded-json.d.ts +4 -0
  38. package/core/bounded-json.d.ts.map +1 -0
  39. package/core/bounded-json.js +38 -0
  40. package/core/cache-state.d.ts +9 -0
  41. package/core/cache-state.d.ts.map +1 -1
  42. package/core/cache-state.js +10 -0
  43. package/core/capabilities-xml.d.ts +33 -0
  44. package/core/capabilities-xml.d.ts.map +1 -0
  45. package/core/capabilities-xml.js +331 -0
  46. package/core/client.d.ts +4 -1
  47. package/core/client.d.ts.map +1 -1
  48. package/core/client.js +115 -29
  49. package/core/error-classifications.d.ts +153 -0
  50. package/core/error-classifications.d.ts.map +1 -0
  51. package/core/error-classifications.js +140 -0
  52. package/core/error-code-registry.d.ts +158 -0
  53. package/core/error-code-registry.d.ts.map +1 -0
  54. package/core/error-code-registry.js +143 -0
  55. package/core/error-envelope.d.ts +68 -0
  56. package/core/error-envelope.d.ts.map +1 -0
  57. package/core/error-envelope.js +357 -0
  58. package/core/errors.d.ts +45 -29
  59. package/core/errors.d.ts.map +1 -1
  60. package/core/errors.js +97 -50
  61. package/core/geoparquet-sql.d.ts +30 -2
  62. package/core/geoparquet-sql.d.ts.map +1 -1
  63. package/core/geoparquet-sql.js +38 -3
  64. package/core/odata-key-path.d.ts +12 -0
  65. package/core/odata-key-path.d.ts.map +1 -0
  66. package/core/odata-key-path.js +28 -0
  67. package/core/odata-write-codec.d.ts +66 -0
  68. package/core/odata-write-codec.d.ts.map +1 -0
  69. package/core/odata-write-codec.js +1083 -0
  70. package/core/odata.d.ts +59 -7
  71. package/core/odata.d.ts.map +1 -1
  72. package/core/odata.js +431 -99
  73. package/core/ogc-features.d.ts.map +1 -1
  74. package/core/ogc-features.js +3 -0
  75. package/core/ogc-maps.d.ts +7 -0
  76. package/core/ogc-maps.d.ts.map +1 -1
  77. package/core/ogc-maps.js +46 -7
  78. package/core/ogc-processes.d.ts +2 -1
  79. package/core/ogc-processes.d.ts.map +1 -1
  80. package/core/ogc-processes.js +33 -5
  81. package/core/ogc-records.d.ts +9 -0
  82. package/core/ogc-records.d.ts.map +1 -1
  83. package/core/ogc-records.js +78 -29
  84. package/core/ogc-tiles.d.ts +10 -1
  85. package/core/ogc-tiles.d.ts.map +1 -1
  86. package/core/ogc-tiles.js +56 -17
  87. package/core/path-utils.d.ts +9 -0
  88. package/core/path-utils.d.ts.map +1 -1
  89. package/core/path-utils.js +19 -0
  90. package/core/protocol-transport.d.ts +1 -0
  91. package/core/protocol-transport.d.ts.map +1 -1
  92. package/core/request-pipeline.d.ts.map +1 -1
  93. package/core/request-pipeline.js +1 -1
  94. package/core/spatial-filter.d.ts +8 -4
  95. package/core/spatial-filter.d.ts.map +1 -1
  96. package/core/spatial-filter.js +206 -16
  97. package/core/stac-static.d.ts +6 -2
  98. package/core/stac-static.d.ts.map +1 -1
  99. package/core/stac-static.js +260 -69
  100. package/core/surfaces.d.ts.map +1 -1
  101. package/core/surfaces.js +69 -5
  102. package/core/types.d.ts +125 -7
  103. package/core/types.d.ts.map +1 -1
  104. package/core/wfs-capabilities.d.ts +2 -0
  105. package/core/wfs-capabilities.d.ts.map +1 -1
  106. package/core/wfs-capabilities.js +8 -1
  107. package/core/wfs.d.ts.map +1 -1
  108. package/core/wfs.js +10 -0
  109. package/core/wms-capabilities.d.ts +56 -84
  110. package/core/wms-capabilities.d.ts.map +1 -1
  111. package/core/wms-capabilities.js +212 -509
  112. package/core/wmts-capabilities.d.ts +62 -62
  113. package/core/wmts-capabilities.d.ts.map +1 -1
  114. package/core/wmts-capabilities.js +224 -371
  115. package/esri-compat/editor.d.ts +8 -0
  116. package/esri-compat/editor.d.ts.map +1 -1
  117. package/esri-compat/editor.js +13 -0
  118. package/esri-compat/feature-layer.d.ts +2 -0
  119. package/esri-compat/feature-layer.d.ts.map +1 -1
  120. package/esri-compat/feature-layer.js +1 -0
  121. package/esri-compat/layer-list.d.ts +11 -0
  122. package/esri-compat/layer-list.d.ts.map +1 -1
  123. package/esri-compat/layer-list.js +49 -0
  124. package/esri-compat/legend.d.ts +10 -0
  125. package/esri-compat/legend.d.ts.map +1 -1
  126. package/esri-compat/legend.js +27 -0
  127. package/esri-compat/portal.d.ts +197 -0
  128. package/esri-compat/portal.d.ts.map +1 -0
  129. package/esri-compat/portal.js +251 -0
  130. package/esri-compat/renderer-objects.d.ts +40 -0
  131. package/esri-compat/renderer-objects.d.ts.map +1 -0
  132. package/esri-compat/renderer-objects.js +62 -0
  133. package/esri-compat/sketch.d.ts +43 -0
  134. package/esri-compat/sketch.d.ts.map +1 -1
  135. package/esri-compat/sketch.js +46 -0
  136. package/esri-compat/snapping.d.ts +43 -0
  137. package/esri-compat/snapping.d.ts.map +1 -0
  138. package/esri-compat/snapping.js +45 -0
  139. package/esri-compat/url.d.ts.map +1 -1
  140. package/esri-compat/url.js +1 -1
  141. package/esri-compat/widget-host.d.ts +84 -0
  142. package/esri-compat/widget-host.d.ts.map +1 -0
  143. package/esri-compat/widget-host.js +159 -0
  144. package/generated-app/errors.d.ts +18 -2
  145. package/generated-app/errors.d.ts.map +1 -1
  146. package/generated-app/errors.js +44 -11
  147. package/geocoding/index.d.ts +7 -0
  148. package/geocoding/index.d.ts.map +1 -1
  149. package/geocoding/index.js +5 -0
  150. package/geocoding/provider-http.d.ts +37 -0
  151. package/geocoding/provider-http.d.ts.map +1 -0
  152. package/geocoding/provider-http.js +91 -0
  153. package/geocoding/provider.d.ts +145 -0
  154. package/geocoding/provider.d.ts.map +1 -0
  155. package/geocoding/provider.js +41 -0
  156. package/geocoding/providers/honua.d.ts +28 -0
  157. package/geocoding/providers/honua.d.ts.map +1 -0
  158. package/geocoding/providers/honua.js +68 -0
  159. package/geocoding/providers/nominatim.d.ts +47 -0
  160. package/geocoding/providers/nominatim.d.ts.map +1 -0
  161. package/geocoding/providers/nominatim.js +105 -0
  162. package/geocoding/providers/pelias.d.ts +40 -0
  163. package/geocoding/providers/pelias.d.ts.map +1 -0
  164. package/geocoding/providers/pelias.js +115 -0
  165. package/geocoding/providers/photon.d.ts +39 -0
  166. package/geocoding/providers/photon.d.ts.map +1 -0
  167. package/geocoding/providers/photon.js +107 -0
  168. package/geometry/convert.d.ts +13 -0
  169. package/geometry/convert.d.ts.map +1 -0
  170. package/geometry/convert.js +12 -0
  171. package/geometry/index.d.ts +17 -0
  172. package/geometry/index.d.ts.map +1 -0
  173. package/geometry/index.js +15 -0
  174. package/geometry/internal.d.ts +25 -0
  175. package/geometry/internal.d.ts.map +1 -0
  176. package/geometry/internal.js +40 -0
  177. package/geometry/ops.d.ts +71 -0
  178. package/geometry/ops.d.ts.map +1 -0
  179. package/geometry/ops.js +147 -0
  180. package/geometry/project.d.ts +40 -0
  181. package/geometry/project.d.ts.map +1 -0
  182. package/geometry/project.js +88 -0
  183. package/geometry/types.d.ts +36 -0
  184. package/geometry/types.d.ts.map +1 -0
  185. package/geometry/types.js +12 -0
  186. package/map/automatic-mount-integration.d.ts +134 -0
  187. package/map/automatic-mount-integration.d.ts.map +1 -0
  188. package/map/automatic-mount-integration.js +305 -0
  189. package/map/automatic-source-strategy.d.ts +125 -0
  190. package/map/automatic-source-strategy.d.ts.map +1 -0
  191. package/map/automatic-source-strategy.js +494 -0
  192. package/map/data-to-map-bridge.d.ts +293 -0
  193. package/map/data-to-map-bridge.d.ts.map +1 -0
  194. package/map/data-to-map-bridge.js +817 -0
  195. package/map/geojson-projection.d.ts +33 -0
  196. package/map/geojson-projection.d.ts.map +1 -0
  197. package/map/geojson-projection.js +118 -0
  198. package/map/index.d.ts +14 -0
  199. package/map/index.d.ts.map +1 -1
  200. package/map/index.js +8 -0
  201. package/map/raster-source-spec.d.ts +30 -0
  202. package/map/raster-source-spec.d.ts.map +1 -0
  203. package/map/raster-source-spec.js +190 -0
  204. package/map/raster-source-strategy.d.ts +65 -0
  205. package/map/raster-source-strategy.d.ts.map +1 -0
  206. package/map/raster-source-strategy.js +232 -0
  207. package/map/source-to-maplibre.d.ts +91 -0
  208. package/map/source-to-maplibre.d.ts.map +1 -0
  209. package/map/source-to-maplibre.js +454 -0
  210. package/map/temporal-playback.d.ts +139 -0
  211. package/map/temporal-playback.d.ts.map +1 -0
  212. package/map/temporal-playback.js +247 -0
  213. package/package.json +33 -2
  214. package/query-planner/canonical.d.ts +7 -0
  215. package/query-planner/canonical.d.ts.map +1 -0
  216. package/query-planner/canonical.js +145 -0
  217. package/query-planner/cql2-json.d.ts +17 -0
  218. package/query-planner/cql2-json.d.ts.map +1 -0
  219. package/query-planner/cql2-json.js +646 -0
  220. package/query-planner/diagnostics.d.ts +35 -0
  221. package/query-planner/diagnostics.d.ts.map +1 -0
  222. package/query-planner/diagnostics.js +373 -0
  223. package/query-planner/duckdb.d.ts +79 -0
  224. package/query-planner/duckdb.d.ts.map +1 -0
  225. package/query-planner/duckdb.js +758 -0
  226. package/query-planner/execution-context.d.ts +5 -0
  227. package/query-planner/execution-context.d.ts.map +1 -0
  228. package/query-planner/execution-context.js +50 -0
  229. package/query-planner/executor.d.ts +5 -0
  230. package/query-planner/executor.d.ts.map +1 -0
  231. package/query-planner/executor.js +223 -0
  232. package/query-planner/geoservices.d.ts +91 -0
  233. package/query-planner/geoservices.d.ts.map +1 -0
  234. package/query-planner/geoservices.js +667 -0
  235. package/query-planner/grpc.d.ts +100 -0
  236. package/query-planner/grpc.d.ts.map +1 -0
  237. package/query-planner/grpc.js +736 -0
  238. package/query-planner/index.d.ts +44 -0
  239. package/query-planner/index.d.ts.map +1 -0
  240. package/query-planner/index.js +30 -0
  241. package/query-planner/ir.d.ts +20 -0
  242. package/query-planner/ir.d.ts.map +1 -0
  243. package/query-planner/ir.js +417 -0
  244. package/query-planner/local-aggregate.d.ts +5 -0
  245. package/query-planner/local-aggregate.d.ts.map +1 -0
  246. package/query-planner/local-aggregate.js +126 -0
  247. package/query-planner/odata.d.ts +48 -0
  248. package/query-planner/odata.d.ts.map +1 -0
  249. package/query-planner/odata.js +662 -0
  250. package/query-planner/ogc-compiler.d.ts +55 -0
  251. package/query-planner/ogc-compiler.d.ts.map +1 -0
  252. package/query-planner/ogc-compiler.js +480 -0
  253. package/query-planner/ogc-features.d.ts +53 -0
  254. package/query-planner/ogc-features.d.ts.map +1 -0
  255. package/query-planner/ogc-features.js +617 -0
  256. package/query-planner/planner.d.ts +17 -0
  257. package/query-planner/planner.d.ts.map +1 -0
  258. package/query-planner/planner.js +818 -0
  259. package/query-planner/resource.d.ts +94 -0
  260. package/query-planner/resource.d.ts.map +1 -0
  261. package/query-planner/resource.js +526 -0
  262. package/query-planner/semantic-canonical.d.ts +15 -0
  263. package/query-planner/semantic-canonical.d.ts.map +1 -0
  264. package/query-planner/semantic-canonical.js +62 -0
  265. package/query-planner/semantic-compat.d.ts +10 -0
  266. package/query-planner/semantic-compat.d.ts.map +1 -0
  267. package/query-planner/semantic-compat.js +35 -0
  268. package/query-planner/semantic-compiler.d.ts +64 -0
  269. package/query-planner/semantic-compiler.d.ts.map +1 -0
  270. package/query-planner/semantic-compiler.js +81 -0
  271. package/query-planner/semantic-literals.d.ts +30 -0
  272. package/query-planner/semantic-literals.d.ts.map +1 -0
  273. package/query-planner/semantic-literals.js +133 -0
  274. package/query-planner/semantic-types.d.ts +265 -0
  275. package/query-planner/semantic-types.d.ts.map +1 -0
  276. package/query-planner/semantic-types.js +1 -0
  277. package/query-planner/semantic.d.ts +54 -0
  278. package/query-planner/semantic.d.ts.map +1 -0
  279. package/query-planner/semantic.js +1421 -0
  280. package/query-planner/types.d.ts +560 -0
  281. package/query-planner/types.d.ts.map +1 -0
  282. package/query-planner/types.js +49 -0
  283. package/query-planner/wfs-semantic.d.ts +58 -0
  284. package/query-planner/wfs-semantic.d.ts.map +1 -0
  285. package/query-planner/wfs-semantic.js +547 -0
  286. package/query-planner/wfs.d.ts +6 -0
  287. package/query-planner/wfs.d.ts.map +1 -0
  288. package/query-planner/wfs.js +71 -0
  289. package/realtime/contract.d.ts +142 -0
  290. package/realtime/contract.d.ts.map +1 -0
  291. package/realtime/contract.js +154 -0
  292. package/realtime/honua-server.d.ts.map +1 -1
  293. package/realtime/honua-server.js +13 -8
  294. package/realtime/index.d.ts +19 -4
  295. package/realtime/index.d.ts.map +1 -1
  296. package/realtime/index.js +14 -4
  297. package/realtime/odata-delta.d.ts +114 -0
  298. package/realtime/odata-delta.d.ts.map +1 -0
  299. package/realtime/odata-delta.js +483 -0
  300. package/realtime/resumable-transport.d.ts +111 -0
  301. package/realtime/resumable-transport.d.ts.map +1 -0
  302. package/realtime/resumable-transport.js +406 -0
  303. package/realtime/resumable.d.ts +104 -0
  304. package/realtime/resumable.d.ts.map +1 -0
  305. package/realtime/resumable.js +632 -0
  306. package/realtime/sse.d.ts.map +1 -1
  307. package/realtime/sse.js +27 -23
  308. package/realtime/websocket.d.ts +60 -0
  309. package/realtime/websocket.d.ts.map +1 -0
  310. package/realtime/websocket.js +157 -0
  311. package/realtime/wire.d.ts +27 -0
  312. package/realtime/wire.d.ts.map +1 -0
  313. package/realtime/wire.js +57 -0
  314. package/replica-sync/errors.d.ts +2 -1
  315. package/replica-sync/errors.d.ts.map +1 -1
  316. package/replica-sync/errors.js +33 -2
  317. package/runtime/edit-snapping.d.ts +107 -0
  318. package/runtime/edit-snapping.d.ts.map +1 -0
  319. package/runtime/edit-snapping.js +190 -0
  320. package/runtime/errors.d.ts +3 -2
  321. package/runtime/errors.d.ts.map +1 -1
  322. package/runtime/errors.js +19 -2
  323. package/runtime/index.d.ts +6 -0
  324. package/runtime/index.d.ts.map +1 -1
  325. package/runtime/index.js +3 -0
  326. package/runtime/maplibre-renderer.d.ts +41 -0
  327. package/runtime/maplibre-renderer.d.ts.map +1 -0
  328. package/runtime/maplibre-renderer.js +322 -0
  329. package/runtime/query-tiles.d.ts +2 -1
  330. package/runtime/query-tiles.d.ts.map +1 -1
  331. package/runtime/query-tiles.js +6 -2
  332. package/runtime/source-bridge.d.ts +4 -4
  333. package/runtime/source-bridge.d.ts.map +1 -1
  334. package/runtime/source-bridge.js +9 -56
  335. package/runtime/style-interactions.d.ts +3 -2
  336. package/runtime/style-interactions.d.ts.map +1 -1
  337. package/runtime/style-interactions.js +11 -3
  338. package/runtime/terra-draw-sketch.d.ts +275 -0
  339. package/runtime/terra-draw-sketch.d.ts.map +1 -0
  340. package/runtime/terra-draw-sketch.js +404 -0
  341. package/scene-workspace/index.d.ts +4 -0
  342. package/scene-workspace/index.d.ts.map +1 -1
  343. package/scene-workspace/index.js +2 -0
  344. package/scene-workspace/source-to-cesium.d.ts +116 -0
  345. package/scene-workspace/source-to-cesium.d.ts.map +1 -0
  346. package/scene-workspace/source-to-cesium.js +791 -0
  347. package/scene-workspace/state-sync.d.ts +147 -0
  348. package/scene-workspace/state-sync.d.ts.map +1 -0
  349. package/scene-workspace/state-sync.js +1123 -0
  350. package/source-capability-registry.d.ts +1 -0
  351. package/source-capability-registry.js +1 -0
  352. package/source-capability-types.d.ts +186 -0
  353. package/source-capability-types.js +7 -0
  354. package/style/index.d.ts +2 -0
  355. package/style/index.d.ts.map +1 -1
  356. package/style/index.js +2 -0
  357. package/style/renderers.d.ts +326 -0
  358. package/style/renderers.d.ts.map +1 -0
  359. package/style/renderers.js +517 -0
  360. package/web-components/controller.d.ts +2 -0
  361. package/web-components/controller.d.ts.map +1 -1
  362. package/web-components/controller.js +49 -8
  363. package/web-components/elements.d.ts +95 -1
  364. package/web-components/elements.d.ts.map +1 -1
  365. package/web-components/elements.js +458 -19
  366. package/web-components/index.d.ts +8 -1
  367. package/web-components/index.d.ts.map +1 -1
  368. package/web-components/index.js +7 -0
  369. package/web-components/maplibre-renderer.d.ts.map +1 -1
  370. package/web-components/maplibre-renderer.js +87 -0
  371. package/web-components/measurement.d.ts +69 -0
  372. package/web-components/measurement.d.ts.map +1 -0
  373. package/web-components/measurement.js +523 -0
  374. package/web-components/types.d.ts +109 -0
  375. package/web-components/types.d.ts.map +1 -1
  376. package/webmap/convert-renderer.d.ts +24 -3
  377. package/webmap/convert-renderer.d.ts.map +1 -1
  378. package/webmap/convert-renderer.js +93 -112
  379. package/webmap/index.d.ts +1 -1
  380. package/webmap/index.d.ts.map +1 -1
  381. package/webmap/index.js +1 -1
@@ -0,0 +1,791 @@
1
+ /**
2
+ * Experimental accepted-plan Source -> Cesium entity workflow.
3
+ *
4
+ * The projection half is renderer-neutral and SSR safe. Cesium is resolved
5
+ * only while mounting, either through an injected module/loader or a lazy
6
+ * optional-peer import.
7
+ *
8
+ * @experimental Not covered by the pre-1.0 semver contract.
9
+ */
10
+ import { HonuaCapabilityNotSupportedError } from "../core/errors.js";
11
+ import { canonicalStringify, toJsonValue } from "../query-planner/canonical.js";
12
+ import { queryFromCanonical, queryIrSourceIdentity } from "../query-planner/ir.js";
13
+ import { hashQueryPlanV1 } from "../query-planner/planner.js";
14
+ import { HonuaQueryPlanExecutionError, } from "../query-planner/types.js";
15
+ export const DEFAULT_CESIUM_ENTITY_LIMIT = 10_000;
16
+ export class HonuaCesiumEntityAdapterError extends Error {
17
+ code;
18
+ detail;
19
+ constructor(code, message, detail, options) {
20
+ super(message, options);
21
+ this.code = code;
22
+ this.detail = detail;
23
+ this.name = "HonuaCesiumEntityAdapterError";
24
+ }
25
+ }
26
+ export function projectSourceToCesium(source, plan, result, options = {}) {
27
+ assertProjectionPlanContext(source, plan);
28
+ const maxEntities = validatePlanAndOptions(source, plan, options);
29
+ if (result.aggregateRows !== undefined)
30
+ throw unsupportedPlan(plan);
31
+ const queryLimit = plan.ir.query.pagination?.limit;
32
+ if (result.features.length > queryLimit) {
33
+ throw new HonuaCesiumEntityAdapterError("entity-limit-exceeded", `Source returned ${result.features.length} features for accepted query limit ${queryLimit}.`, { queryLimit, returnedFeatureCount: result.features.length });
34
+ }
35
+ const sourceId = `honua-${safeId(source.descriptor.id)}`;
36
+ const idField = options.featureIdField ?? source.descriptor.schema?.primaryKey;
37
+ const diagnostics = [
38
+ diagnostic(source, plan, "strategy-selected", "info", "project", "exact", "Selected bounded Cesium entity query strategy.", {
39
+ maxEntities,
40
+ }),
41
+ ];
42
+ const entities = [];
43
+ let unsupportedGeometry = 0;
44
+ let missingIdentity = 0;
45
+ let invalidIntervals = 0;
46
+ let unsupportedVerticalDatum = 0;
47
+ let unsupportedAttributes = 0;
48
+ const entityIds = new Set();
49
+ for (const feature of result.features) {
50
+ const attributes = snapshotJsonAttributes(feature.attributes);
51
+ if (!attributes) {
52
+ unsupportedAttributes += 1;
53
+ continue;
54
+ }
55
+ const featureId = idField ? attributes[idField] : undefined;
56
+ if (typeof featureId !== "string" && typeof featureId !== "number") {
57
+ missingIdentity += 1;
58
+ continue;
59
+ }
60
+ if (geometryHasZ(feature.geometry) && options.verticalDatum !== "ellipsoidal-wgs84") {
61
+ unsupportedVerticalDatum += 1;
62
+ continue;
63
+ }
64
+ const geometry = projectGeometry(feature);
65
+ if (!geometry) {
66
+ unsupportedGeometry += 1;
67
+ continue;
68
+ }
69
+ const interval = options.time ? projectInterval(attributes, options.time) : undefined;
70
+ if (options.time && !interval) {
71
+ invalidIntervals += 1;
72
+ continue;
73
+ }
74
+ const entityId = `${sourceId}:${typeof featureId === "number" ? "n" : "s"}:${encodeURIComponent(String(featureId))}`;
75
+ if (entityIds.has(entityId)) {
76
+ throw new HonuaCesiumEntityAdapterError("entity-conflict", `Accepted query returned duplicate stable feature identity "${String(featureId)}".`, { entityId, featureId });
77
+ }
78
+ entityIds.add(entityId);
79
+ entities.push(Object.freeze({
80
+ id: entityId,
81
+ featureId,
82
+ properties: attributes,
83
+ geometry: immutableJsonSnapshot(geometry),
84
+ ...(interval ? { interval: immutableJsonSnapshot(interval) } : {}),
85
+ }));
86
+ if (entities.length > maxEntities) {
87
+ throw new HonuaCesiumEntityAdapterError("entity-limit-exceeded", `Cesium projection exceeded the ${maxEntities} entity safety ceiling.`, { maxEntities, sourceId: source.descriptor.id });
88
+ }
89
+ }
90
+ if (result.features.length === 0) {
91
+ diagnostics.push(diagnostic(source, plan, "empty-result", "info", "execute", "exact", "The accepted plan returned no features."));
92
+ }
93
+ if (result.exceededTransferLimit) {
94
+ diagnostics.push(diagnostic(source, plan, "transfer-limit", "warning", "execute", "unsupported", "The rendered page is not the complete source result.", {
95
+ renderedEntityCount: entities.length,
96
+ }));
97
+ }
98
+ if (result.degraded?.length) {
99
+ diagnostics.push(diagnostic(source, plan, "source-degraded", "warning", "execute", "unsupported", "The source reported degraded execution semantics.", {
100
+ reasons: result.degraded.map((entry) => entry.reason),
101
+ }));
102
+ }
103
+ if (missingIdentity > 0) {
104
+ diagnostics.push(diagnostic(source, plan, "identity-missing", "warning", "project", "unsupported", `${missingIdentity} feature(s) lacked stable identity and were omitted.`, {
105
+ featureIdField: idField,
106
+ omittedFeatureCount: missingIdentity,
107
+ }));
108
+ }
109
+ if (unsupportedAttributes > 0) {
110
+ diagnostics.push(diagnostic(source, plan, "attributes-unsupported", "warning", "project", "unsupported", `${unsupportedAttributes} feature attribute object(s) were not strict JSON-like values and were omitted.`, { omittedFeatureCount: unsupportedAttributes }));
111
+ }
112
+ if (unsupportedGeometry > 0) {
113
+ diagnostics.push(diagnostic(source, plan, "geometry-unsupported", "warning", "project", "unsupported", `${unsupportedGeometry} feature geometry value(s) were omitted.`, {
114
+ omittedFeatureCount: unsupportedGeometry,
115
+ }));
116
+ }
117
+ if (unsupportedVerticalDatum > 0) {
118
+ diagnostics.push(diagnostic(source, plan, "vertical-datum-unsupported", "warning", "project", "unsupported", `${unsupportedVerticalDatum} feature(s) carried Z values without an explicit supported vertical datum and were omitted.`, { supportedVerticalDatum: "ellipsoidal-wgs84", omittedFeatureCount: unsupportedVerticalDatum }));
119
+ }
120
+ if (invalidIntervals > 0) {
121
+ diagnostics.push(diagnostic(source, plan, "time-interval-invalid", "warning", "project", "unsupported", `${invalidIntervals} feature time interval(s) were invalid and omitted.`, {
122
+ omittedFeatureCount: invalidIntervals,
123
+ }));
124
+ }
125
+ return Object.freeze({
126
+ strategy: "entity-query",
127
+ sourceId,
128
+ planId: plan.id,
129
+ planFingerprint: plan.fingerprint,
130
+ sourceVersion: plan.ir.source.sourceVersion,
131
+ schemaVersion: plan.ir.source.schemaVersion,
132
+ authorizationScope: Object.freeze([...plan.ir.source.authorizationScope]),
133
+ entities: Object.freeze(entities),
134
+ diagnostics: Object.freeze(diagnostics),
135
+ state: diagnostics.some((entry) => entry.severity === "warning")
136
+ ? "degraded"
137
+ : entities.length === 0
138
+ ? "empty"
139
+ : "ready",
140
+ });
141
+ }
142
+ export async function mountSourceToCesium(collection, source, plan, options = {}) {
143
+ const mountOptions = snapshotMountOptions(options);
144
+ assertProjectionPlanContext(source, plan);
145
+ validatePlanAndOptions(source, plan, mountOptions);
146
+ const lifecycle = new AbortController();
147
+ const initialSignal = combineSignals([lifecycle.signal, mountOptions.signal]);
148
+ initialSignal.throwIfAborted();
149
+ assertExecutionContext(source, plan, executionOptions(mountOptions));
150
+ const cesium = await resolveCesium(mountOptions.cesium);
151
+ initialSignal.throwIfAborted();
152
+ const result = await executeAcceptedPlan(source, plan, initialSignal);
153
+ initialSignal.throwIfAborted();
154
+ let projection = projectSourceToCesium(source, plan, result, mountOptions);
155
+ const initialSpecs = materializeProjection(cesium, projection);
156
+ assertEntityIdsAvailable(collection, initialSpecs.keys());
157
+ let mounted = new Map();
158
+ const attemptedInitialIds = [];
159
+ try {
160
+ for (const [id, spec] of initialSpecs) {
161
+ initialSignal.throwIfAborted();
162
+ attemptedInitialIds.push(id);
163
+ mounted.set(id, spec);
164
+ collection.add(spec);
165
+ initialSignal.throwIfAborted();
166
+ }
167
+ }
168
+ catch (cause) {
169
+ // Include each attempted id: some renderer wrappers mutate and then throw.
170
+ const failures = removeIds(collection, attemptedInitialIds);
171
+ mounted = new Map();
172
+ if (initialSignal.aborted && failures.length === 0)
173
+ throw initialSignal.reason;
174
+ throw mutationError("Failed to mount Cesium entities transactionally.", cause, failures);
175
+ }
176
+ let state = projection.state;
177
+ let diagnostics = projection.diagnostics;
178
+ let refreshTail = Promise.resolve();
179
+ let lifecycleEpoch = 0;
180
+ let disposeActive = false;
181
+ const runRefresh = async (refreshOptions) => {
182
+ if (state === "disposed" || state === "disposing") {
183
+ throw new HonuaCesiumEntityAdapterError("disposed", "Cannot refresh a disposed Cesium entity mount.");
184
+ }
185
+ const currentEpoch = lifecycleEpoch;
186
+ const refreshContext = snapshotExecutionOptions(refreshOptions);
187
+ const signal = combineSignals([lifecycle.signal, refreshContext.signal]);
188
+ signal.throwIfAborted();
189
+ assertExecutionContext(source, plan, { ...executionOptions(mountOptions), ...refreshContext });
190
+ const nextResult = await executeAcceptedPlan(source, plan, signal);
191
+ signal.throwIfAborted();
192
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, signal);
193
+ const next = projectSourceToCesium(source, plan, nextResult, mountOptions);
194
+ signal.throwIfAborted();
195
+ const nextSpecs = materializeProjection(cesium, next);
196
+ const previous = new Map(mounted);
197
+ assertEntityIdsAvailable(collection, [...nextSpecs.keys()].filter((id) => !previous.has(id)));
198
+ const attemptedNextIds = [];
199
+ try {
200
+ removeIdsOrThrow(collection, [...previous.keys()]);
201
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, signal);
202
+ mounted = new Map();
203
+ for (const [id, spec] of nextSpecs) {
204
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, signal);
205
+ attemptedNextIds.push(id);
206
+ mounted.set(id, spec);
207
+ collection.add(spec);
208
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, signal);
209
+ }
210
+ }
211
+ catch (cause) {
212
+ const ownedSpecs = new Map([...previous, ...nextSpecs]);
213
+ const cleanupFailures = removeIds(collection, [...mounted.keys(), ...attemptedNextIds]);
214
+ mounted = presentOwnedSpecs(collection, ownedSpecs);
215
+ if (lifecycleInvalidated(currentEpoch, lifecycleEpoch, state)) {
216
+ if (cleanupFailures.length > 0) {
217
+ throw mutationError("Cesium entity disposal interrupted refresh and cleanup was incomplete.", cause, cleanupFailures);
218
+ }
219
+ throw lifecycle.signal.reason;
220
+ }
221
+ const restoreFailures = [];
222
+ for (const [id, spec] of previous) {
223
+ try {
224
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, lifecycle.signal);
225
+ mounted.set(id, spec);
226
+ if (!collection.getById(id))
227
+ collection.add(spec);
228
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, lifecycle.signal);
229
+ }
230
+ catch (error) {
231
+ mounted.delete(id);
232
+ restoreFailures.push(error);
233
+ if (lifecycleInvalidated(currentEpoch, lifecycleEpoch, state))
234
+ break;
235
+ }
236
+ }
237
+ if (lifecycleInvalidated(currentEpoch, lifecycleEpoch, state)) {
238
+ const rollbackOwnedSpecs = new Map(mounted);
239
+ const disposalCleanupFailures = removeIds(collection, [...rollbackOwnedSpecs.keys()]);
240
+ mounted = presentOwnedSpecs(collection, rollbackOwnedSpecs);
241
+ if (disposalCleanupFailures.length > 0) {
242
+ throw mutationError("Cesium entity disposal interrupted rollback and cleanup was incomplete.", cause, [
243
+ ...cleanupFailures,
244
+ ...restoreFailures,
245
+ ...disposalCleanupFailures,
246
+ ]);
247
+ }
248
+ throw lifecycle.signal.reason;
249
+ }
250
+ if (signal.aborted && cleanupFailures.length === 0 && restoreFailures.length === 0)
251
+ throw signal.reason;
252
+ state = "degraded";
253
+ diagnostics = Object.freeze([
254
+ ...diagnostics,
255
+ diagnostic(source, plan, "incremental-update-failed", "warning", "update", "unsupported", "Cesium entity rebuild failed; restoration was attempted.", {
256
+ rollbackSucceeded: cleanupFailures.length === 0 && restoreFailures.length === 0,
257
+ }),
258
+ ]);
259
+ throw mutationError("Failed to rebuild the mounted Cesium entity snapshot.", cause, [
260
+ ...cleanupFailures,
261
+ ...restoreFailures,
262
+ ]);
263
+ }
264
+ assertLifecycleActive(currentEpoch, lifecycleEpoch, state, signal);
265
+ diagnostics = Object.freeze([
266
+ ...next.diagnostics,
267
+ diagnostic(source, plan, "incremental-update", "info", "update", "equivalent", "Rebuilt the bounded entity snapshot while preserving stable entity ids.", {
268
+ previousEntityCount: previous.size,
269
+ nextEntityCount: mounted.size,
270
+ rebuildBoundary: "entity-snapshot",
271
+ }),
272
+ ]);
273
+ projection = Object.freeze({ ...next, diagnostics });
274
+ state = next.state;
275
+ return projection;
276
+ };
277
+ return {
278
+ strategy: "entity-query",
279
+ sourceId: projection.sourceId,
280
+ get entityIds() {
281
+ return [...mounted.keys()];
282
+ },
283
+ planId: plan.id,
284
+ planFingerprint: plan.fingerprint,
285
+ get state() {
286
+ return state;
287
+ },
288
+ get diagnostics() {
289
+ return diagnostics;
290
+ },
291
+ refresh(refreshOptions = {}) {
292
+ const refreshContext = snapshotExecutionOptions(refreshOptions);
293
+ const value = refreshTail.then(() => runRefresh(refreshContext));
294
+ refreshTail = value.then(() => undefined, () => undefined);
295
+ return value;
296
+ },
297
+ dispose() {
298
+ if (state === "disposed")
299
+ return;
300
+ if (disposeActive)
301
+ return;
302
+ disposeActive = true;
303
+ lifecycleEpoch += 1;
304
+ lifecycle.abort(new DOMException("Cesium entity mount disposed", "AbortError"));
305
+ state = "disposing";
306
+ try {
307
+ const failures = [];
308
+ for (const id of [...mounted.keys()]) {
309
+ try {
310
+ if (!collection.getById(id) || collection.removeById(id))
311
+ mounted.delete(id);
312
+ else
313
+ failures.push(new Error(`Cesium refused to remove entity "${id}".`));
314
+ }
315
+ catch (error) {
316
+ failures.push(error);
317
+ }
318
+ }
319
+ if (failures.length > 0) {
320
+ throw mutationError("Cesium entity disposal is incomplete and may be retried.", failures[0], failures);
321
+ }
322
+ state = "disposed";
323
+ }
324
+ finally {
325
+ disposeActive = false;
326
+ }
327
+ },
328
+ };
329
+ }
330
+ async function resolveCesium(injected) {
331
+ try {
332
+ const runtime = typeof injected === "function"
333
+ ? await injected()
334
+ : (injected ?? (await import("cesium")));
335
+ assertCesiumRuntime(runtime);
336
+ return runtime;
337
+ }
338
+ catch (cause) {
339
+ if (cause instanceof HonuaCesiumEntityAdapterError)
340
+ throw cause;
341
+ throw new HonuaCesiumEntityAdapterError("peer-unavailable", "Cesium entity mounting requires the optional cesium peer or an injected runtime module.", undefined, { cause });
342
+ }
343
+ }
344
+ function materializeProjection(cesium, projection) {
345
+ return new Map(projection.entities.map((item) => [item.id, materializeEntity(cesium, item)]));
346
+ }
347
+ function materializeEntity(cesium, item) {
348
+ const positions = item.geometry.kind === "point"
349
+ ? [toCartesian(cesium, item.geometry.coordinates)]
350
+ : item.geometry.coordinates.map((coordinate) => toCartesian(cesium, coordinate));
351
+ const geometry = item.geometry.kind === "point"
352
+ ? { position: positions[0], point: { pixelSize: 8 } }
353
+ : item.geometry.kind === "polyline"
354
+ ? { polyline: { positions, width: 2 } }
355
+ : { polygon: { hierarchy: new cesium.PolygonHierarchy(positions) } };
356
+ const availability = item.interval
357
+ ? new cesium.TimeIntervalCollection([
358
+ new cesium.TimeInterval({
359
+ start: cesium.JulianDate.fromIso8601(item.interval.start),
360
+ stop: cesium.JulianDate.fromIso8601(item.interval.end),
361
+ }),
362
+ ])
363
+ : undefined;
364
+ return Object.freeze({
365
+ id: item.id,
366
+ properties: item.properties,
367
+ ...geometry,
368
+ ...(availability ? { availability } : {}),
369
+ });
370
+ }
371
+ function toCartesian(cesium, coordinate) {
372
+ return cesium.Cartesian3.fromDegrees(coordinate[0], coordinate[1], coordinate[2]);
373
+ }
374
+ function projectGeometry(feature) {
375
+ const value = feature.geometry;
376
+ if (!value || typeof value !== "object")
377
+ return undefined;
378
+ const geometry = value;
379
+ if (isFiniteNumber(geometry.x) && isFiniteNumber(geometry.y)) {
380
+ if (!validLongitudeLatitude(geometry.x, geometry.y) || !validOptionalHeight(geometry, "z"))
381
+ return undefined;
382
+ const height = isFiniteNumber(geometry.z) ? geometry.z : 0;
383
+ return { kind: "point", coordinates: [geometry.x, geometry.y, height] };
384
+ }
385
+ if (geometry.type === "Point") {
386
+ const coordinate = coordinate3(geometry.coordinates);
387
+ return coordinate ? { kind: "point", coordinates: coordinate } : undefined;
388
+ }
389
+ if (geometry.type === "LineString") {
390
+ const coordinates = coordinates3(geometry.coordinates);
391
+ return coordinates && coordinates.length >= 2 ? { kind: "polyline", coordinates } : undefined;
392
+ }
393
+ if (geometry.type === "Polygon") {
394
+ const rings = geometry.coordinates;
395
+ if (!Array.isArray(rings) || rings.length !== 1 || !Object.hasOwn(rings, 0))
396
+ return undefined;
397
+ const coordinates = coordinates3(rings[0]);
398
+ return coordinates && validRing(coordinates) ? { kind: "polygon", coordinates } : undefined;
399
+ }
400
+ if (Array.isArray(geometry.paths) && geometry.paths.length === 1 && Object.hasOwn(geometry.paths, 0)) {
401
+ const coordinates = coordinates3(geometry.paths[0]);
402
+ return coordinates && coordinates.length >= 2 ? { kind: "polyline", coordinates } : undefined;
403
+ }
404
+ if (Array.isArray(geometry.rings) && geometry.rings.length === 1 && Object.hasOwn(geometry.rings, 0)) {
405
+ const coordinates = coordinates3(geometry.rings[0]);
406
+ return coordinates && validRing(coordinates) ? { kind: "polygon", coordinates } : undefined;
407
+ }
408
+ return undefined;
409
+ }
410
+ function geometryHasZ(value) {
411
+ if (!value || typeof value !== "object")
412
+ return false;
413
+ const geometry = value;
414
+ if (Object.hasOwn(geometry, "z"))
415
+ return true;
416
+ const candidate = geometry.coordinates ?? geometry.paths ?? geometry.rings;
417
+ return coordinateTreeHasZ(candidate);
418
+ }
419
+ function coordinateTreeHasZ(value) {
420
+ if (!Array.isArray(value))
421
+ return false;
422
+ if (Object.hasOwn(value, 0) && Object.hasOwn(value, 1) && isFiniteNumber(value[0]) && isFiniteNumber(value[1]))
423
+ return value.length >= 3 && Object.hasOwn(value, 2);
424
+ for (let index = 0; index < value.length; index += 1) {
425
+ if (!Object.hasOwn(value, index))
426
+ return false;
427
+ if (coordinateTreeHasZ(value[index]))
428
+ return true;
429
+ }
430
+ return false;
431
+ }
432
+ function coordinate3(value) {
433
+ if (!Array.isArray(value) ||
434
+ value.length < 2 ||
435
+ value.length > 3 ||
436
+ !Object.hasOwn(value, 0) ||
437
+ !Object.hasOwn(value, 1) ||
438
+ (value.length === 3 && !Object.hasOwn(value, 2)) ||
439
+ !isFiniteNumber(value[0]) ||
440
+ !isFiniteNumber(value[1]) ||
441
+ !validLongitudeLatitude(value[0], value[1]) ||
442
+ (value.length === 3 && !isFiniteNumber(value[2])))
443
+ return undefined;
444
+ return [value[0], value[1], value.length === 3 ? value[2] : 0];
445
+ }
446
+ function coordinates3(value) {
447
+ if (!Array.isArray(value))
448
+ return undefined;
449
+ const result = [];
450
+ for (let index = 0; index < value.length; index += 1) {
451
+ if (!Object.hasOwn(value, index))
452
+ return undefined;
453
+ const coordinate = coordinate3(value[index]);
454
+ if (!coordinate)
455
+ return undefined;
456
+ result.push(coordinate);
457
+ }
458
+ return result;
459
+ }
460
+ function validLongitudeLatitude(longitude, latitude) {
461
+ return longitude >= -180 && longitude <= 180 && latitude >= -90 && latitude <= 90;
462
+ }
463
+ function validOptionalHeight(geometry, key) {
464
+ return !Object.hasOwn(geometry, key) || geometry[key] === undefined || isFiniteNumber(geometry[key]);
465
+ }
466
+ function validRing(coordinates) {
467
+ if (coordinates.length < 4)
468
+ return false;
469
+ const first = coordinates[0];
470
+ const last = coordinates.at(-1);
471
+ return first !== undefined && last !== undefined && first.every((value, index) => value === last[index]);
472
+ }
473
+ function projectInterval(attributes, time) {
474
+ const start = isoInstant(attributes[time.startField]);
475
+ const end = isoInstant(attributes[time.endField]);
476
+ if (!start || !end || Date.parse(end) < Date.parse(start))
477
+ return undefined;
478
+ return { start, end };
479
+ }
480
+ function isoInstant(value) {
481
+ if (typeof value === "number" && !Number.isSafeInteger(value))
482
+ return undefined;
483
+ if (typeof value === "string" && !validOffsetIsoInstant(value))
484
+ return undefined;
485
+ const date = typeof value === "number" || typeof value === "string" ? new Date(value) : undefined;
486
+ return date && Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
487
+ }
488
+ const OFFSET_ISO_INSTANT = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.\d{1,3})?(?:Z|([+-])(\d{2}):(\d{2}))$/;
489
+ function validOffsetIsoInstant(value) {
490
+ const match = OFFSET_ISO_INSTANT.exec(value);
491
+ if (!match)
492
+ return false;
493
+ const [, yearText, monthText, dayText, hourText, minuteText, secondText, , offsetHourText, offsetMinuteText] = match;
494
+ const year = Number(yearText);
495
+ const month = Number(monthText);
496
+ const day = Number(dayText);
497
+ const hour = Number(hourText);
498
+ const minute = Number(minuteText);
499
+ const second = Number(secondText);
500
+ const offsetHour = offsetHourText === undefined ? 0 : Number(offsetHourText);
501
+ const offsetMinute = offsetMinuteText === undefined ? 0 : Number(offsetMinuteText);
502
+ const daysInMonth = month >= 1 && month <= 12 ? new Date(Date.UTC(year, month, 0)).getUTCDate() : 0;
503
+ return (day >= 1 &&
504
+ day <= daysInMonth &&
505
+ hour <= 23 &&
506
+ minute <= 59 &&
507
+ second <= 59 &&
508
+ offsetHour <= 14 &&
509
+ offsetMinute <= 59 &&
510
+ (offsetHour < 14 || offsetMinute === 0));
511
+ }
512
+ function validatePlanAndOptions(source, plan, options) {
513
+ if (!source.capabilities.has("query")) {
514
+ throw new HonuaCapabilityNotSupportedError("query", source.descriptor.protocol, source.descriptor.id);
515
+ }
516
+ const step = plan.steps[0];
517
+ const limit = plan.ir.query.pagination?.limit;
518
+ if (plan.steps.length !== 1 ||
519
+ step?.engine !== "remote" ||
520
+ step.operation !== "query" ||
521
+ plan.ir.query.aggregation !== undefined ||
522
+ plan.ir.query.returnGeometry !== true ||
523
+ !Number.isSafeInteger(limit) ||
524
+ limit <= 0) {
525
+ throw unsupportedPlan(plan);
526
+ }
527
+ if (canonicalStringify(toJsonValue(step.query)) !== canonicalStringify(toJsonValue(plan.ir.query))) {
528
+ throw new HonuaQueryPlanExecutionError("invalid-plan", "Remote query step does not match the accepted canonical query IR.");
529
+ }
530
+ const maxEntities = positiveInteger(options.maxEntities, DEFAULT_CESIUM_ENTITY_LIMIT, "maxEntities");
531
+ if (limit > maxEntities) {
532
+ throw new HonuaCesiumEntityAdapterError("entity-limit-exceeded", `Accepted query limit ${limit} exceeds the Cesium entity ceiling ${maxEntities}.`, { queryLimit: limit, maxEntities });
533
+ }
534
+ const outSr = plan.ir.query.outSr;
535
+ if (outSr !== 4326 && outSr !== "4326" && outSr !== "EPSG:4326") {
536
+ throw new HonuaCesiumEntityAdapterError("unsupported-crs", "Cesium entity projection requires an accepted query with outSr 4326; implicit or non-WGS84 coordinates are not reinterpreted.", { outSr });
537
+ }
538
+ const idField = options.featureIdField ?? source.descriptor.schema?.primaryKey;
539
+ if (!idField) {
540
+ throw new HonuaCesiumEntityAdapterError("invalid-option", "Cesium entity projection requires featureIdField or descriptor.schema.primaryKey.");
541
+ }
542
+ if (options.time !== undefined && (!options.time.startField || !options.time.endField)) {
543
+ throw new HonuaCesiumEntityAdapterError("invalid-option", "time.startField and time.endField must be non-empty.");
544
+ }
545
+ return maxEntities;
546
+ }
547
+ function unsupportedPlan(plan) {
548
+ return new HonuaCesiumEntityAdapterError("unsupported-plan", "Cesium entity mounting requires one bounded remote feature query with geometry.", { planId: plan.id, operations: plan.steps.map((step) => step.operation) });
549
+ }
550
+ function executeAcceptedPlan(source, plan, signal) {
551
+ const step = plan.steps[0];
552
+ if (!step || step.engine !== "remote" || step.operation !== "query")
553
+ throw unsupportedPlan(plan);
554
+ return source.query(queryFromCanonical(step.query, signal));
555
+ }
556
+ function assertProjectionPlanContext(source, plan) {
557
+ if (hashQueryPlanV1(plan) !== plan.fingerprint) {
558
+ throw new HonuaQueryPlanExecutionError("invalid-plan", "Plan content does not match its fingerprint.");
559
+ }
560
+ const identity = queryIrSourceIdentity(source.descriptor, {
561
+ schemaVersion: plan.ir.source.schemaVersion,
562
+ sourceVersion: plan.ir.source.sourceVersion,
563
+ authorizationScope: plan.ir.source.authorizationScope,
564
+ });
565
+ const runtimeCapabilities = [...source.capabilities].sort();
566
+ if (canonicalStringify(toJsonValue(identity)) !== canonicalStringify(toJsonValue(plan.ir.source)) ||
567
+ canonicalStringify(toJsonValue(runtimeCapabilities)) !==
568
+ canonicalStringify(toJsonValue([...source.descriptor.capabilities].sort()))) {
569
+ throw new HonuaQueryPlanExecutionError("plan-context-mismatch", "Source identity or capabilities do not match the accepted Cesium projection context.");
570
+ }
571
+ }
572
+ function assertExecutionContext(source, plan, options) {
573
+ const current = queryIrSourceIdentity(source.descriptor, options);
574
+ if (canonicalStringify(toJsonValue(current)) !== canonicalStringify(toJsonValue(plan.ir.source))) {
575
+ throw new HonuaQueryPlanExecutionError("plan-context-mismatch", "Source identity, version, capabilities, or authorization scope changed after planning.");
576
+ }
577
+ }
578
+ function diagnostic(source, plan, code, severity, stage, fidelity, message, detail) {
579
+ return Object.freeze({
580
+ code,
581
+ severity,
582
+ stage,
583
+ fidelity,
584
+ sourceId: source.descriptor.id,
585
+ planId: plan.id,
586
+ message,
587
+ ...(detail ? { detail: immutableJsonSnapshot(detail) } : {}),
588
+ });
589
+ }
590
+ function executionOptions(options) {
591
+ return {
592
+ ...(options.signal ? { signal: options.signal } : {}),
593
+ ...(options.schemaVersion ? { schemaVersion: options.schemaVersion } : {}),
594
+ ...(options.sourceVersion ? { sourceVersion: options.sourceVersion } : {}),
595
+ ...(options.authorizationScope ? { authorizationScope: options.authorizationScope } : {}),
596
+ };
597
+ }
598
+ function snapshotExecutionOptions(options) {
599
+ return Object.freeze({
600
+ ...(options.signal ? { signal: options.signal } : {}),
601
+ ...(options.schemaVersion !== undefined ? { schemaVersion: options.schemaVersion } : {}),
602
+ ...(options.sourceVersion !== undefined ? { sourceVersion: options.sourceVersion } : {}),
603
+ ...(options.authorizationScope ? { authorizationScope: Object.freeze([...options.authorizationScope]) } : {}),
604
+ });
605
+ }
606
+ function snapshotMountOptions(options) {
607
+ const execution = snapshotExecutionOptions(options);
608
+ return Object.freeze({
609
+ ...execution,
610
+ ...(options.cesium ? { cesium: options.cesium } : {}),
611
+ ...(options.featureIdField !== undefined ? { featureIdField: options.featureIdField } : {}),
612
+ ...(options.maxEntities !== undefined ? { maxEntities: options.maxEntities } : {}),
613
+ ...(options.verticalDatum !== undefined ? { verticalDatum: options.verticalDatum } : {}),
614
+ ...(options.time
615
+ ? {
616
+ time: Object.freeze({ startField: options.time.startField, endField: options.time.endField }),
617
+ }
618
+ : {}),
619
+ });
620
+ }
621
+ function assertLifecycleActive(expectedEpoch, currentEpoch, state, signal) {
622
+ if (lifecycleInvalidated(expectedEpoch, currentEpoch, state)) {
623
+ throw new DOMException("Cesium entity mount disposed", "AbortError");
624
+ }
625
+ signal.throwIfAborted();
626
+ }
627
+ function lifecycleInvalidated(expectedEpoch, currentEpoch, state) {
628
+ return expectedEpoch !== currentEpoch || state === "disposed" || state === "disposing";
629
+ }
630
+ function assertCesiumRuntime(value) {
631
+ const runtime = value;
632
+ if (!runtime ||
633
+ typeof runtime.Cartesian3?.fromDegrees !== "function" ||
634
+ typeof runtime.JulianDate?.fromIso8601 !== "function" ||
635
+ typeof runtime.TimeInterval !== "function" ||
636
+ typeof runtime.TimeIntervalCollection !== "function" ||
637
+ typeof runtime.PolygonHierarchy !== "function") {
638
+ throw new HonuaCesiumEntityAdapterError("peer-unavailable", "The Cesium runtime does not provide the entity adapter APIs required by this mount.");
639
+ }
640
+ }
641
+ const INVALID_JSON_ATTRIBUTE = Symbol("invalid-json-attribute");
642
+ function immutableJsonSnapshot(value) {
643
+ const snapshot = snapshotJsonValue(value, new Set());
644
+ if (snapshot === INVALID_JSON_ATTRIBUTE)
645
+ throw new TypeError("Internal value is not JSON-like.");
646
+ return snapshot;
647
+ }
648
+ function snapshotJsonAttributes(value) {
649
+ const snapshot = snapshotJsonValue(value, new Set());
650
+ return snapshot !== INVALID_JSON_ATTRIBUTE && isPlainObject(snapshot)
651
+ ? snapshot
652
+ : undefined;
653
+ }
654
+ function snapshotJsonValue(value, ancestors) {
655
+ if (value === null || typeof value === "string" || typeof value === "boolean")
656
+ return value;
657
+ if (typeof value === "number")
658
+ return Number.isFinite(value) ? value : INVALID_JSON_ATTRIBUTE;
659
+ if (typeof value !== "object")
660
+ return INVALID_JSON_ATTRIBUTE;
661
+ if (ancestors.has(value))
662
+ return INVALID_JSON_ATTRIBUTE;
663
+ ancestors.add(value);
664
+ if (Array.isArray(value)) {
665
+ const copy = [];
666
+ for (let index = 0; index < value.length; index += 1) {
667
+ if (!Object.hasOwn(value, index)) {
668
+ ancestors.delete(value);
669
+ return INVALID_JSON_ATTRIBUTE;
670
+ }
671
+ const entry = snapshotJsonValue(value[index], ancestors);
672
+ if (entry === INVALID_JSON_ATTRIBUTE) {
673
+ ancestors.delete(value);
674
+ return INVALID_JSON_ATTRIBUTE;
675
+ }
676
+ copy.push(entry);
677
+ }
678
+ ancestors.delete(value);
679
+ return Object.freeze(copy);
680
+ }
681
+ if (!isPlainObject(value)) {
682
+ ancestors.delete(value);
683
+ return INVALID_JSON_ATTRIBUTE;
684
+ }
685
+ const copy = {};
686
+ for (const key of Reflect.ownKeys(value)) {
687
+ if (typeof key !== "string") {
688
+ ancestors.delete(value);
689
+ return INVALID_JSON_ATTRIBUTE;
690
+ }
691
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
692
+ if (!descriptor?.enumerable || !("value" in descriptor)) {
693
+ ancestors.delete(value);
694
+ return INVALID_JSON_ATTRIBUTE;
695
+ }
696
+ const entry = snapshotJsonValue(descriptor.value, ancestors);
697
+ if (entry === INVALID_JSON_ATTRIBUTE) {
698
+ ancestors.delete(value);
699
+ return INVALID_JSON_ATTRIBUTE;
700
+ }
701
+ Object.defineProperty(copy, key, {
702
+ value: entry,
703
+ enumerable: true,
704
+ writable: false,
705
+ configurable: false,
706
+ });
707
+ }
708
+ ancestors.delete(value);
709
+ return Object.freeze(copy);
710
+ }
711
+ function isPlainObject(value) {
712
+ if (value === null || typeof value !== "object" || Array.isArray(value))
713
+ return false;
714
+ const prototype = Object.getPrototypeOf(value);
715
+ return prototype === Object.prototype || prototype === null;
716
+ }
717
+ function removeIds(collection, ids) {
718
+ const failures = [];
719
+ for (const id of new Set(ids)) {
720
+ try {
721
+ if (collection.getById(id) && !collection.removeById(id))
722
+ failures.push(new Error(`Cesium refused to remove entity "${id}".`));
723
+ }
724
+ catch (error) {
725
+ failures.push(error);
726
+ }
727
+ }
728
+ return failures;
729
+ }
730
+ function removeIdsOrThrow(collection, ids) {
731
+ const failures = removeIds(collection, ids);
732
+ if (failures.length > 0)
733
+ throw failures[0];
734
+ }
735
+ function presentOwnedSpecs(collection, specs) {
736
+ const present = new Map();
737
+ for (const [id, spec] of specs) {
738
+ try {
739
+ if (collection.getById(id))
740
+ present.set(id, spec);
741
+ }
742
+ catch {
743
+ // Conservatively retain ownership so a later disposal can retry the id.
744
+ present.set(id, spec);
745
+ }
746
+ }
747
+ return present;
748
+ }
749
+ function mutationError(message, cause, failures) {
750
+ return new HonuaCesiumEntityAdapterError("renderer-mutation-failed", message, { cleanupFailureCount: failures.length, cleanupFailures: failures.map(errorMessage) }, { cause });
751
+ }
752
+ function entityConflict(id) {
753
+ return new HonuaCesiumEntityAdapterError("entity-conflict", `Cesium entity "${id}" already exists.`, {
754
+ entityId: id,
755
+ });
756
+ }
757
+ function assertEntityIdsAvailable(collection, ids) {
758
+ for (const id of ids) {
759
+ if (collection.getById(id))
760
+ throw entityConflict(id);
761
+ }
762
+ }
763
+ function combineSignals(signals) {
764
+ const available = signals.filter((signal) => signal !== undefined);
765
+ return available.length === 1 ? available[0] : AbortSignal.any(available);
766
+ }
767
+ function safeId(value) {
768
+ const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-");
769
+ let start = 0;
770
+ let end = normalized.length;
771
+ while (start < end && normalized.charCodeAt(start) === 45)
772
+ start += 1;
773
+ while (end > start && normalized.charCodeAt(end - 1) === 45)
774
+ end -= 1;
775
+ return normalized.slice(start, end) || "source";
776
+ }
777
+ function positiveInteger(value, fallback, name) {
778
+ const candidate = value ?? fallback;
779
+ if (!Number.isSafeInteger(candidate) || candidate <= 0) {
780
+ throw new HonuaCesiumEntityAdapterError("invalid-option", `${name} must be a positive safe integer.`, {
781
+ [name]: value,
782
+ });
783
+ }
784
+ return candidate;
785
+ }
786
+ function isFiniteNumber(value) {
787
+ return typeof value === "number" && Number.isFinite(value);
788
+ }
789
+ function errorMessage(error) {
790
+ return error instanceof Error ? error.message : String(error);
791
+ }