@honua/react 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 (363) 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 +12 -1
  14. package/contract/index.d.ts.map +1 -1
  15. package/contract/index.js +4 -0
  16. package/contract/pmtiles.d.ts +193 -0
  17. package/contract/pmtiles.d.ts.map +1 -0
  18. package/contract/pmtiles.js +195 -0
  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 +57 -15
  32. package/contract/source.d.ts.map +1 -1
  33. package/contract/source.js +368 -65
  34. package/contract/types.d.ts +171 -6
  35. package/contract/types.d.ts.map +1 -1
  36. package/contract/types.js +14 -14
  37. package/core/auth/client-credentials-provider.d.ts +51 -0
  38. package/core/auth/client-credentials-provider.d.ts.map +1 -0
  39. package/core/auth/client-credentials-provider.js +115 -0
  40. package/core/auth/credential-store.d.ts +52 -0
  41. package/core/auth/credential-store.d.ts.map +1 -0
  42. package/core/auth/credential-store.js +82 -0
  43. package/core/auth/index.d.ts +23 -0
  44. package/core/auth/index.d.ts.map +1 -0
  45. package/core/auth/index.js +20 -0
  46. package/core/auth/oauth2-provider.d.ts +114 -0
  47. package/core/auth/oauth2-provider.d.ts.map +1 -0
  48. package/core/auth/oauth2-provider.js +408 -0
  49. package/core/auth/pkce.d.ts +25 -0
  50. package/core/auth/pkce.d.ts.map +1 -0
  51. package/core/auth/pkce.js +46 -0
  52. package/core/auth/static-providers.d.ts +20 -0
  53. package/core/auth/static-providers.d.ts.map +1 -0
  54. package/core/auth/static-providers.js +26 -0
  55. package/core/auth/token-endpoint.d.ts +40 -0
  56. package/core/auth/token-endpoint.d.ts.map +1 -0
  57. package/core/auth/token-endpoint.js +133 -0
  58. package/core/auth/types.d.ts +144 -0
  59. package/core/auth/types.d.ts.map +1 -0
  60. package/core/auth/types.js +8 -0
  61. package/core/bounded-json.d.ts +4 -0
  62. package/core/bounded-json.d.ts.map +1 -0
  63. package/core/bounded-json.js +38 -0
  64. package/core/cache-state.d.ts +9 -0
  65. package/core/cache-state.d.ts.map +1 -1
  66. package/core/cache-state.js +10 -0
  67. package/core/capabilities-xml.d.ts +33 -0
  68. package/core/capabilities-xml.d.ts.map +1 -0
  69. package/core/capabilities-xml.js +331 -0
  70. package/core/client.d.ts +35 -2
  71. package/core/client.d.ts.map +1 -1
  72. package/core/client.js +167 -29
  73. package/core/error-classifications.d.ts +153 -0
  74. package/core/error-classifications.d.ts.map +1 -0
  75. package/core/error-classifications.js +140 -0
  76. package/core/error-code-registry.d.ts +158 -0
  77. package/core/error-code-registry.d.ts.map +1 -0
  78. package/core/error-code-registry.js +143 -0
  79. package/core/error-envelope.d.ts +68 -0
  80. package/core/error-envelope.d.ts.map +1 -0
  81. package/core/error-envelope.js +357 -0
  82. package/core/errors.d.ts +73 -25
  83. package/core/errors.d.ts.map +1 -1
  84. package/core/errors.js +113 -46
  85. package/core/geoparquet-sql.d.ts +190 -0
  86. package/core/geoparquet-sql.d.ts.map +1 -0
  87. package/core/geoparquet-sql.js +368 -0
  88. package/core/odata-key-path.d.ts +12 -0
  89. package/core/odata-key-path.d.ts.map +1 -0
  90. package/core/odata-key-path.js +28 -0
  91. package/core/odata-write-codec.d.ts +66 -0
  92. package/core/odata-write-codec.d.ts.map +1 -0
  93. package/core/odata-write-codec.js +1083 -0
  94. package/core/odata.d.ts +59 -7
  95. package/core/odata.d.ts.map +1 -1
  96. package/core/odata.js +431 -99
  97. package/core/ogc-endpoint-layout.d.ts +70 -0
  98. package/core/ogc-endpoint-layout.d.ts.map +1 -0
  99. package/core/ogc-endpoint-layout.js +173 -0
  100. package/core/ogc-features.d.ts.map +1 -1
  101. package/core/ogc-features.js +35 -17
  102. package/core/ogc-maps.d.ts +7 -0
  103. package/core/ogc-maps.d.ts.map +1 -1
  104. package/core/ogc-maps.js +46 -7
  105. package/core/ogc-processes.d.ts +2 -1
  106. package/core/ogc-processes.d.ts.map +1 -1
  107. package/core/ogc-processes.js +33 -5
  108. package/core/ogc-records.d.ts +9 -0
  109. package/core/ogc-records.d.ts.map +1 -1
  110. package/core/ogc-records.js +78 -29
  111. package/core/ogc-tiles.d.ts +10 -1
  112. package/core/ogc-tiles.d.ts.map +1 -1
  113. package/core/ogc-tiles.js +56 -17
  114. package/core/path-utils.d.ts +9 -0
  115. package/core/path-utils.d.ts.map +1 -1
  116. package/core/path-utils.js +19 -0
  117. package/core/protocol-transport.d.ts +1 -0
  118. package/core/protocol-transport.d.ts.map +1 -1
  119. package/core/request-pipeline.d.ts.map +1 -1
  120. package/core/request-pipeline.js +1 -1
  121. package/core/spatial-filter.d.ts +8 -4
  122. package/core/spatial-filter.d.ts.map +1 -1
  123. package/core/spatial-filter.js +206 -16
  124. package/core/stac-static.d.ts +55 -0
  125. package/core/stac-static.d.ts.map +1 -0
  126. package/core/stac-static.js +386 -0
  127. package/core/stac.d.ts +12 -0
  128. package/core/stac.d.ts.map +1 -1
  129. package/core/stac.js +45 -15
  130. package/core/surfaces.d.ts +13 -0
  131. package/core/surfaces.d.ts.map +1 -1
  132. package/core/surfaces.js +127 -16
  133. package/core/types.d.ts +174 -7
  134. package/core/types.d.ts.map +1 -1
  135. package/core/wfs-capabilities.d.ts +12 -0
  136. package/core/wfs-capabilities.d.ts.map +1 -1
  137. package/core/wfs-capabilities.js +22 -3
  138. package/core/wfs.d.ts +13 -0
  139. package/core/wfs.d.ts.map +1 -1
  140. package/core/wfs.js +35 -5
  141. package/core/wms-capabilities.d.ts +56 -84
  142. package/core/wms-capabilities.d.ts.map +1 -1
  143. package/core/wms-capabilities.js +212 -509
  144. package/core/wmts-capabilities.d.ts +62 -62
  145. package/core/wmts-capabilities.d.ts.map +1 -1
  146. package/core/wmts-capabilities.js +224 -371
  147. package/esri-compat/editor.d.ts +8 -0
  148. package/esri-compat/editor.d.ts.map +1 -1
  149. package/esri-compat/editor.js +13 -0
  150. package/esri-compat/feature-layer.d.ts +2 -0
  151. package/esri-compat/feature-layer.d.ts.map +1 -1
  152. package/esri-compat/feature-layer.js +1 -0
  153. package/esri-compat/identity-manager.d.ts +43 -0
  154. package/esri-compat/identity-manager.d.ts.map +1 -1
  155. package/esri-compat/identity-manager.js +131 -1
  156. package/esri-compat/layer-list.d.ts +11 -0
  157. package/esri-compat/layer-list.d.ts.map +1 -1
  158. package/esri-compat/layer-list.js +49 -0
  159. package/esri-compat/legend.d.ts +10 -0
  160. package/esri-compat/legend.d.ts.map +1 -1
  161. package/esri-compat/legend.js +27 -0
  162. package/esri-compat/oauth-info.d.ts +15 -0
  163. package/esri-compat/oauth-info.d.ts.map +1 -1
  164. package/esri-compat/oauth-info.js +27 -0
  165. package/esri-compat/portal.d.ts +197 -0
  166. package/esri-compat/portal.d.ts.map +1 -0
  167. package/esri-compat/portal.js +251 -0
  168. package/esri-compat/renderer-objects.d.ts +40 -0
  169. package/esri-compat/renderer-objects.d.ts.map +1 -0
  170. package/esri-compat/renderer-objects.js +62 -0
  171. package/esri-compat/sketch.d.ts +43 -0
  172. package/esri-compat/sketch.d.ts.map +1 -1
  173. package/esri-compat/sketch.js +46 -0
  174. package/esri-compat/snapping.d.ts +43 -0
  175. package/esri-compat/snapping.d.ts.map +1 -0
  176. package/esri-compat/snapping.js +45 -0
  177. package/esri-compat/url.d.ts.map +1 -1
  178. package/esri-compat/url.js +1 -1
  179. package/esri-compat/widget-host.d.ts +84 -0
  180. package/esri-compat/widget-host.d.ts.map +1 -0
  181. package/esri-compat/widget-host.js +159 -0
  182. package/filter-registry/index.d.ts +145 -0
  183. package/filter-registry/index.d.ts.map +1 -0
  184. package/filter-registry/index.js +531 -0
  185. package/generated-app/errors.d.ts +18 -2
  186. package/generated-app/errors.d.ts.map +1 -1
  187. package/generated-app/errors.js +44 -11
  188. package/map/automatic-mount-integration.d.ts +134 -0
  189. package/map/automatic-mount-integration.d.ts.map +1 -0
  190. package/map/automatic-mount-integration.js +305 -0
  191. package/map/automatic-source-strategy.d.ts +125 -0
  192. package/map/automatic-source-strategy.d.ts.map +1 -0
  193. package/map/automatic-source-strategy.js +494 -0
  194. package/map/data-to-map-bridge.d.ts +293 -0
  195. package/map/data-to-map-bridge.d.ts.map +1 -0
  196. package/map/data-to-map-bridge.js +817 -0
  197. package/map/geojson-projection.d.ts +33 -0
  198. package/map/geojson-projection.d.ts.map +1 -0
  199. package/map/geojson-projection.js +118 -0
  200. package/map/index.d.ts +14 -0
  201. package/map/index.d.ts.map +1 -1
  202. package/map/index.js +8 -0
  203. package/map/raster-source-spec.d.ts +30 -0
  204. package/map/raster-source-spec.d.ts.map +1 -0
  205. package/map/raster-source-spec.js +190 -0
  206. package/map/raster-source-strategy.d.ts +65 -0
  207. package/map/raster-source-strategy.d.ts.map +1 -0
  208. package/map/raster-source-strategy.js +232 -0
  209. package/map/source-to-maplibre.d.ts +91 -0
  210. package/map/source-to-maplibre.d.ts.map +1 -0
  211. package/map/source-to-maplibre.js +454 -0
  212. package/map/temporal-playback.d.ts +139 -0
  213. package/map/temporal-playback.d.ts.map +1 -0
  214. package/map/temporal-playback.js +247 -0
  215. package/package.json +19 -1
  216. package/query-planner/canonical.d.ts +7 -0
  217. package/query-planner/canonical.d.ts.map +1 -0
  218. package/query-planner/canonical.js +145 -0
  219. package/query-planner/cql2-json.d.ts +17 -0
  220. package/query-planner/cql2-json.d.ts.map +1 -0
  221. package/query-planner/cql2-json.js +646 -0
  222. package/query-planner/diagnostics.d.ts +35 -0
  223. package/query-planner/diagnostics.d.ts.map +1 -0
  224. package/query-planner/diagnostics.js +373 -0
  225. package/query-planner/duckdb.d.ts +79 -0
  226. package/query-planner/duckdb.d.ts.map +1 -0
  227. package/query-planner/duckdb.js +758 -0
  228. package/query-planner/execution-context.d.ts +5 -0
  229. package/query-planner/execution-context.d.ts.map +1 -0
  230. package/query-planner/execution-context.js +50 -0
  231. package/query-planner/executor.d.ts +5 -0
  232. package/query-planner/executor.d.ts.map +1 -0
  233. package/query-planner/executor.js +223 -0
  234. package/query-planner/geoservices.d.ts +91 -0
  235. package/query-planner/geoservices.d.ts.map +1 -0
  236. package/query-planner/geoservices.js +667 -0
  237. package/query-planner/grpc.d.ts +100 -0
  238. package/query-planner/grpc.d.ts.map +1 -0
  239. package/query-planner/grpc.js +736 -0
  240. package/query-planner/index.d.ts +44 -0
  241. package/query-planner/index.d.ts.map +1 -0
  242. package/query-planner/index.js +30 -0
  243. package/query-planner/ir.d.ts +20 -0
  244. package/query-planner/ir.d.ts.map +1 -0
  245. package/query-planner/ir.js +417 -0
  246. package/query-planner/local-aggregate.d.ts +5 -0
  247. package/query-planner/local-aggregate.d.ts.map +1 -0
  248. package/query-planner/local-aggregate.js +126 -0
  249. package/query-planner/odata.d.ts +48 -0
  250. package/query-planner/odata.d.ts.map +1 -0
  251. package/query-planner/odata.js +662 -0
  252. package/query-planner/ogc-compiler.d.ts +55 -0
  253. package/query-planner/ogc-compiler.d.ts.map +1 -0
  254. package/query-planner/ogc-compiler.js +480 -0
  255. package/query-planner/ogc-features.d.ts +53 -0
  256. package/query-planner/ogc-features.d.ts.map +1 -0
  257. package/query-planner/ogc-features.js +617 -0
  258. package/query-planner/planner.d.ts +17 -0
  259. package/query-planner/planner.d.ts.map +1 -0
  260. package/query-planner/planner.js +818 -0
  261. package/query-planner/resource.d.ts +94 -0
  262. package/query-planner/resource.d.ts.map +1 -0
  263. package/query-planner/resource.js +526 -0
  264. package/query-planner/semantic-canonical.d.ts +15 -0
  265. package/query-planner/semantic-canonical.d.ts.map +1 -0
  266. package/query-planner/semantic-canonical.js +62 -0
  267. package/query-planner/semantic-compat.d.ts +10 -0
  268. package/query-planner/semantic-compat.d.ts.map +1 -0
  269. package/query-planner/semantic-compat.js +35 -0
  270. package/query-planner/semantic-compiler.d.ts +64 -0
  271. package/query-planner/semantic-compiler.d.ts.map +1 -0
  272. package/query-planner/semantic-compiler.js +81 -0
  273. package/query-planner/semantic-literals.d.ts +30 -0
  274. package/query-planner/semantic-literals.d.ts.map +1 -0
  275. package/query-planner/semantic-literals.js +133 -0
  276. package/query-planner/semantic-types.d.ts +265 -0
  277. package/query-planner/semantic-types.d.ts.map +1 -0
  278. package/query-planner/semantic-types.js +1 -0
  279. package/query-planner/semantic.d.ts +54 -0
  280. package/query-planner/semantic.d.ts.map +1 -0
  281. package/query-planner/semantic.js +1421 -0
  282. package/query-planner/types.d.ts +560 -0
  283. package/query-planner/types.d.ts.map +1 -0
  284. package/query-planner/types.js +49 -0
  285. package/query-planner/wfs-semantic.d.ts +58 -0
  286. package/query-planner/wfs-semantic.d.ts.map +1 -0
  287. package/query-planner/wfs-semantic.js +547 -0
  288. package/query-planner/wfs.d.ts +6 -0
  289. package/query-planner/wfs.d.ts.map +1 -0
  290. package/query-planner/wfs.js +71 -0
  291. package/react/external-map.d.ts +67 -0
  292. package/react/external-map.d.ts.map +1 -0
  293. package/react/external-map.js +63 -0
  294. package/react/honua-map.d.ts.map +1 -1
  295. package/react/honua-map.js +3 -2
  296. package/react/honua-source-layer.d.ts +110 -0
  297. package/react/honua-source-layer.d.ts.map +1 -0
  298. package/react/honua-source-layer.js +101 -0
  299. package/react/hooks.d.ts +28 -0
  300. package/react/hooks.d.ts.map +1 -1
  301. package/react/hooks.js +26 -4
  302. package/react/index.d.ts +8 -0
  303. package/react/index.d.ts.map +1 -1
  304. package/react/index.js +5 -0
  305. package/react/query-cache.d.ts +26 -4
  306. package/react/query-cache.d.ts.map +1 -1
  307. package/react/query-cache.js +51 -8
  308. package/react/selection.d.ts +177 -0
  309. package/react/selection.d.ts.map +1 -0
  310. package/react/selection.js +0 -0
  311. package/react/use-mounted-source.d.ts +69 -0
  312. package/react/use-mounted-source.d.ts.map +1 -0
  313. package/react/use-mounted-source.js +346 -0
  314. package/runtime/edit-snapping.d.ts +107 -0
  315. package/runtime/edit-snapping.d.ts.map +1 -0
  316. package/runtime/edit-snapping.js +190 -0
  317. package/runtime/errors.d.ts +3 -2
  318. package/runtime/errors.d.ts.map +1 -1
  319. package/runtime/errors.js +19 -2
  320. package/runtime/index.d.ts +8 -2
  321. package/runtime/index.d.ts.map +1 -1
  322. package/runtime/index.js +4 -4
  323. package/runtime/load-package.d.ts.map +1 -1
  324. package/runtime/load-package.js +8 -0
  325. package/runtime/map-package-validation.d.ts +0 -13
  326. package/runtime/map-package-validation.d.ts.map +1 -1
  327. package/runtime/map-package-validation.js +0 -12
  328. package/runtime/map-package.d.ts +1 -1
  329. package/runtime/map-package.d.ts.map +1 -1
  330. package/runtime/maplibre-renderer.d.ts +41 -0
  331. package/runtime/maplibre-renderer.d.ts.map +1 -0
  332. package/runtime/maplibre-renderer.js +322 -0
  333. package/runtime/pmtiles-protocol.d.ts +77 -0
  334. package/runtime/pmtiles-protocol.d.ts.map +1 -0
  335. package/runtime/pmtiles-protocol.js +120 -0
  336. package/runtime/query-tiles.d.ts +2 -1
  337. package/runtime/query-tiles.d.ts.map +1 -1
  338. package/runtime/query-tiles.js +6 -2
  339. package/runtime/source-bridge.d.ts +4 -4
  340. package/runtime/source-bridge.d.ts.map +1 -1
  341. package/runtime/source-bridge.js +36 -56
  342. package/runtime/style-interactions.d.ts +3 -2
  343. package/runtime/style-interactions.d.ts.map +1 -1
  344. package/runtime/style-interactions.js +11 -3
  345. package/runtime/terra-draw-sketch.d.ts +275 -0
  346. package/runtime/terra-draw-sketch.d.ts.map +1 -0
  347. package/runtime/terra-draw-sketch.js +404 -0
  348. package/source-capability-registry.d.ts +1 -0
  349. package/source-capability-registry.js +1 -0
  350. package/source-capability-types.d.ts +186 -0
  351. package/source-capability-types.js +7 -0
  352. package/style/index.d.ts +2 -0
  353. package/style/index.d.ts.map +1 -1
  354. package/style/index.js +2 -0
  355. package/style/renderers.d.ts +326 -0
  356. package/style/renderers.d.ts.map +1 -0
  357. package/style/renderers.js +517 -0
  358. package/webmap/convert-renderer.d.ts +24 -3
  359. package/webmap/convert-renderer.d.ts.map +1 -1
  360. package/webmap/convert-renderer.js +93 -112
  361. package/webmap/index.d.ts +1 -1
  362. package/webmap/index.d.ts.map +1 -1
  363. package/webmap/index.js +1 -1
@@ -1,3 +1,4 @@
1
+ import { HonuaGeometryError } from "./errors.js";
1
2
  /**
2
3
  * Create an envelope (bounding box) spatial filter.
3
4
  *
@@ -62,8 +63,12 @@ export function polygon(rings, spatialReference) {
62
63
  };
63
64
  }
64
65
  /**
65
- * Create an envelope spatial filter centered on a point, approximating a
66
- * circular buffer as a bounding box.
66
+ * Create an axis-aligned envelope spatial filter centered on a point.
67
+ *
68
+ * This is a planar expansion in the input coordinate system's units. It is an
69
+ * envelope approximation, not a circular, geodesic, or topological geometry
70
+ * buffer. Use `buffer` from `@honua/sdk-js/geometry` when a true geometry
71
+ * buffer is required.
67
72
  *
68
73
  * @param x - Center x coordinate
69
74
  * @param y - Center y coordinate
@@ -75,12 +80,25 @@ export function polygon(rings, spatialReference) {
75
80
  * // 0.5-degree bounding box around a point
76
81
  * const req: QueryFeaturesRequest = {
77
82
  * serviceId: "svc", layerId: 0,
78
- * ...buffer(-118.24, 34.05, 0.5),
83
+ * ...bufferEnvelope(-118.24, 34.05, 0.5),
79
84
  * };
80
85
  * ```
81
86
  */
82
- export function buffer(x, y, distance, spatialReference) {
83
- return envelope(x - distance, y - distance, x + distance, y + distance, spatialReference);
87
+ export function bufferEnvelope(x, y, distance, spatialReference) {
88
+ if (![x, y, distance].every(isFiniteNumber) || distance < 0) {
89
+ throw new HonuaGeometryError("malformed-geometry", "Cannot create a buffer envelope: x, y, and distance must be finite numbers and distance must be non-negative", {
90
+ operation: "buffer-envelope",
91
+ reason: "invalid-coordinate-or-distance",
92
+ });
93
+ }
94
+ const bounds = [x - distance, y - distance, x + distance, y + distance];
95
+ if (!bounds.every(isFiniteNumber)) {
96
+ throw new HonuaGeometryError("malformed-geometry", "Cannot create a buffer envelope: computed bounds must be finite", {
97
+ operation: "buffer-envelope",
98
+ reason: "computed-bounds-not-finite",
99
+ });
100
+ }
101
+ return envelope(...bounds, spatialReference);
84
102
  }
85
103
  /**
86
104
  * Wrap an existing geometry with `esriSpatialRelIntersects`.
@@ -131,23 +149,195 @@ export function spatialWithin(geometry) {
131
149
  * Detect the Esri geometry type from a plain geometry object by inspecting
132
150
  * its shape (duck-typing).
133
151
  *
152
+ * @see https://developers.arcgis.com/rest/services-reference/enterprise/geometry-objects/
134
153
  * @internal
135
154
  */
136
155
  function detectGeometryType(geometry) {
137
- if ("xmin" in geometry && "ymin" in geometry && "xmax" in geometry && "ymax" in geometry) {
138
- return "esriGeometryEnvelope";
156
+ if (!isGeometryRecord(geometry)) {
157
+ throw new HonuaGeometryError("malformed-geometry", "Unable to classify geometry: geometry must be a non-null object", {
158
+ operation: "classify",
159
+ reason: "geometry-must-be-object",
160
+ keys: [],
161
+ });
162
+ }
163
+ const keys = Object.keys(geometry).sort();
164
+ const candidates = [
165
+ hasAnyOwn(geometry, ["xmin", "ymin", "xmax", "ymax"]) ? "envelope" : undefined,
166
+ hasOwn(geometry, "rings") ? "polygon" : undefined,
167
+ hasOwn(geometry, "paths") ? "polyline" : undefined,
168
+ hasOwn(geometry, "points") ? "multipoint" : undefined,
169
+ hasAnyOwn(geometry, ["x", "y"]) ? "point" : undefined,
170
+ ].filter((candidate) => candidate !== undefined);
171
+ if (candidates.length === 0) {
172
+ throw geometryClassificationError("unknown-geometry", "no supported Esri geometry shape was found", keys);
173
+ }
174
+ if (candidates.length > 1) {
175
+ throw geometryClassificationError("malformed-geometry", `geometry contains conflicting shape discriminators: ${candidates.join(", ")}`, keys);
176
+ }
177
+ const candidate = candidates[0];
178
+ switch (candidate) {
179
+ case "envelope":
180
+ assertEnvelope(geometry, keys);
181
+ return "esriGeometryEnvelope";
182
+ case "polygon":
183
+ assertParts(geometry, "rings", "polygon", 4, true, keys);
184
+ return "esriGeometryPolygon";
185
+ case "polyline":
186
+ assertParts(geometry, "paths", "polyline", 2, false, keys);
187
+ return "esriGeometryPolyline";
188
+ case "multipoint":
189
+ assertPositions(geometry, keys);
190
+ return "esriGeometryMultipoint";
191
+ case "point":
192
+ assertPoint(geometry, keys);
193
+ return "esriGeometryPoint";
194
+ }
195
+ }
196
+ function isGeometryRecord(value) {
197
+ return typeof value === "object" && value !== null && !Array.isArray(value);
198
+ }
199
+ function hasOwn(value, key) {
200
+ return Object.prototype.hasOwnProperty.call(value, key);
201
+ }
202
+ function hasAnyOwn(value, keys) {
203
+ return keys.some((key) => hasOwn(value, key));
204
+ }
205
+ function isFiniteNumber(value) {
206
+ return typeof value === "number" && Number.isFinite(value);
207
+ }
208
+ function assertPoint(geometry, keys) {
209
+ if (hasOwn(geometry, "x") && geometry.x === null) {
210
+ assertEmptyMembers(geometry, ["y", "z", "m", "id"], "point", keys);
211
+ return;
139
212
  }
140
- if ("rings" in geometry) {
141
- return "esriGeometryPolygon";
213
+ if (!isFiniteNumber(geometry.x) || !isFiniteNumber(geometry.y)) {
214
+ throw geometryClassificationError("malformed-geometry", "point requires finite numeric x and y coordinates", keys, "point");
215
+ }
216
+ assertOptionalFiniteMember(geometry, "z", "point", keys);
217
+ assertOptionalFiniteMember(geometry, "m", "point", keys, true);
218
+ assertOptionalFiniteMember(geometry, "id", "point", keys);
219
+ }
220
+ function assertEnvelope(geometry, keys) {
221
+ if (hasOwn(geometry, "xmin") && geometry.xmin === null) {
222
+ assertEmptyMembers(geometry, ["ymin", "xmax", "ymax", "zmin", "zmax", "mmin", "mmax", "idmin", "idmax"], "envelope", keys);
223
+ return;
142
224
  }
143
- if ("paths" in geometry) {
144
- return "esriGeometryPolyline";
225
+ const { xmin, ymin, xmax, ymax } = geometry;
226
+ if (![xmin, ymin, xmax, ymax].every(isFiniteNumber)) {
227
+ throw geometryClassificationError("malformed-geometry", "envelope requires finite numeric xmin, ymin, xmax, and ymax coordinates", keys, "envelope");
145
228
  }
146
- if ("points" in geometry) {
147
- return "esriGeometryMultipoint";
229
+ if (xmin > xmax || ymin > ymax) {
230
+ throw geometryClassificationError("malformed-geometry", "envelope minimum coordinates must not exceed maximum coordinates", keys, "envelope");
148
231
  }
149
- if ("x" in geometry && "y" in geometry) {
150
- return "esriGeometryPoint";
232
+ assertOptionalBounds(geometry, "zmin", "zmax", "envelope", keys);
233
+ assertOptionalBounds(geometry, "mmin", "mmax", "envelope", keys);
234
+ assertOptionalBounds(geometry, "idmin", "idmax", "envelope", keys);
235
+ }
236
+ function assertPositions(geometry, keys) {
237
+ const value = geometry.points;
238
+ if (!Array.isArray(value)) {
239
+ throw geometryClassificationError("malformed-geometry", "multipoint points must be an array of coordinate positions", keys, "multipoint");
240
+ }
241
+ const dimensions = geometryDimensions(geometry, "multipoint", keys);
242
+ for (const position of value) {
243
+ // ArcGIS permits empty point slots in multipoints and ignores them during
244
+ // spatial evaluation. Preserve that wire-compatible behavior while still
245
+ // rejecting every non-empty malformed position.
246
+ if (Array.isArray(position) && position.length === 0)
247
+ continue;
248
+ assertPosition(position, dimensions, "multipoint", keys);
249
+ }
250
+ }
251
+ function assertParts(geometry, property, shape, minimumPositions, requireClosure, keys) {
252
+ const value = geometry[property];
253
+ if (!Array.isArray(value)) {
254
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} must be an array of coordinate arrays`, keys, shape);
151
255
  }
152
- return "esriGeometryPoint";
256
+ const dimensions = geometryDimensions(geometry, shape, keys);
257
+ for (const part of value) {
258
+ if (!Array.isArray(part)) {
259
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} must contain coordinate arrays`, keys, shape);
260
+ }
261
+ // The REST empty sentinel is an empty outer paths/rings array. Empty inner
262
+ // parts are not canonical and cannot be mixed with populated parts.
263
+ if (part.length < minimumPositions) {
264
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} parts require at least ${minimumPositions} positions`, keys, shape);
265
+ }
266
+ for (const position of part)
267
+ assertPosition(position, dimensions, shape, keys);
268
+ if (requireClosure) {
269
+ const first = part[0];
270
+ const last = part[part.length - 1];
271
+ if (first[0] !== last[0] || first[1] !== last[1]) {
272
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} parts must be closed`, keys, shape);
273
+ }
274
+ }
275
+ }
276
+ }
277
+ function geometryDimensions(geometry, shape, keys) {
278
+ return {
279
+ hasZ: geometryBooleanFlag(geometry, "hasZ", shape, keys),
280
+ hasM: geometryBooleanFlag(geometry, "hasM", shape, keys),
281
+ };
282
+ }
283
+ function geometryBooleanFlag(geometry, property, shape, keys) {
284
+ if (!hasOwn(geometry, property))
285
+ return false;
286
+ if (typeof geometry[property] !== "boolean") {
287
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} must be a boolean when present`, keys, shape);
288
+ }
289
+ return geometry[property];
290
+ }
291
+ function assertPosition(value, dimensions, shape, keys) {
292
+ const minimumArity = dimensions.hasZ ? 3 : 2;
293
+ const maximumArity = minimumArity + (dimensions.hasM ? 1 : 0);
294
+ if (!Array.isArray(value) || value.length < minimumArity || value.length > maximumArity || value.length > 4) {
295
+ throw geometryClassificationError("malformed-geometry", `${shape} positions must match declared hasZ/hasM dimensions and contain at most four ordinates`, keys, shape);
296
+ }
297
+ if (!isFiniteNumber(value[0]) || !isFiniteNumber(value[1])) {
298
+ throw geometryClassificationError("malformed-geometry", `${shape} positions require finite numeric x and y ordinates`, keys, shape);
299
+ }
300
+ if (dimensions.hasZ && !isFiniteNumber(value[2])) {
301
+ throw geometryClassificationError("malformed-geometry", `${shape} positions require a finite z ordinate when hasZ is true`, keys, shape);
302
+ }
303
+ if (dimensions.hasM && value.length === maximumArity) {
304
+ const measure = value[maximumArity - 1];
305
+ if (measure !== null && !isFiniteNumber(measure)) {
306
+ throw geometryClassificationError("malformed-geometry", `${shape} m ordinates must be finite numbers, null, or omitted`, keys, shape);
307
+ }
308
+ }
309
+ }
310
+ function assertEmptyMembers(geometry, members, shape, keys) {
311
+ const contradictory = members.filter((member) => hasOwn(geometry, member) && geometry[member] !== null);
312
+ if (contradictory.length > 0) {
313
+ throw geometryClassificationError("malformed-geometry", `${shape} empty sentinel conflicts with non-null members: ${contradictory.join(", ")}`, keys, shape);
314
+ }
315
+ }
316
+ function assertOptionalFiniteMember(geometry, property, shape, keys, allowNull = false) {
317
+ if (!hasOwn(geometry, property))
318
+ return;
319
+ const value = geometry[property];
320
+ if ((allowNull && value === null) || isFiniteNumber(value))
321
+ return;
322
+ const expectation = allowNull ? "a finite number or null" : "a finite number";
323
+ throw geometryClassificationError("malformed-geometry", `${shape} ${property} must be ${expectation} when present`, keys, shape);
324
+ }
325
+ function assertOptionalBounds(geometry, minimumProperty, maximumProperty, shape, keys) {
326
+ const hasMinimum = hasOwn(geometry, minimumProperty);
327
+ const hasMaximum = hasOwn(geometry, maximumProperty);
328
+ if (!hasMinimum && !hasMaximum)
329
+ return;
330
+ const minimum = geometry[minimumProperty];
331
+ const maximum = geometry[maximumProperty];
332
+ if (!hasMinimum || !hasMaximum || !isFiniteNumber(minimum) || !isFiniteNumber(maximum) || minimum > maximum) {
333
+ throw geometryClassificationError("malformed-geometry", `envelope ${minimumProperty}/${maximumProperty} must be a complete ordered pair of finite numbers`, keys, shape);
334
+ }
335
+ }
336
+ function geometryClassificationError(code, reason, keys, shape) {
337
+ return new HonuaGeometryError(code, `Unable to classify geometry: ${reason}`, {
338
+ operation: "classify",
339
+ reason,
340
+ keys,
341
+ ...(shape === undefined ? {} : { shape }),
342
+ });
153
343
  }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Static STAC catalog reader.
3
+ *
4
+ * A large share of public STAC catalogs are not API servers — they are
5
+ * static `catalog.json` / `collection.json` / item trees served from object
6
+ * storage, with no `/search` endpoint. This reader walks such a tree the
7
+ * spec-driven way: it follows `rel="child"` links to descend catalogs /
8
+ * collections and `rel="item"` links to reach STAC Items, resolving every
9
+ * href against the document it was found in (STAC best-practice relative
10
+ * links). Filtering (`collections` / `bbox` / `datetime` / `limit`) is
11
+ * applied client-side and the result is projected onto the same
12
+ * {@link HonuaStacItemCollectionResponse} envelope the STAC API search path
13
+ * returns, so the canonical `Source` surface is identical across both
14
+ * layouts.
15
+ *
16
+ * @module
17
+ */
18
+ import type { SourceLocator } from "../contract/types.js";
19
+ import type { HonuaClient } from "./client.js";
20
+ import type { HonuaStacItemCollectionResponse } from "./types.js";
21
+ /** Bounded search parameters for a static catalog traversal. */
22
+ export interface StacStaticSearchParams {
23
+ collections?: readonly string[];
24
+ bbox?: readonly [number, number, number, number];
25
+ datetime?: string;
26
+ limit?: number;
27
+ signal?: AbortSignal;
28
+ }
29
+ /**
30
+ * Reader bound to the URL of a static STAC catalog / collection root. The
31
+ * URL is the client baseUrl (the transport resolves same-origin absolute
32
+ * child/item hrefs directly), so `rootUrl` is normally `""` (the baseUrl
33
+ * itself) but may be an absolute `catalog.json` URL.
34
+ */
35
+ export declare class HonuaStacStaticCatalog {
36
+ readonly client: HonuaClient;
37
+ private readonly rootUrl;
38
+ private readonly policy;
39
+ constructor(client: HonuaClient, rootUrl?: string, policy?: SourceLocator["stacStatic"]);
40
+ /**
41
+ * Traverse the catalog tree, collect matching items, and return them in
42
+ * the STAC search envelope shape.
43
+ */
44
+ search(params?: StacStaticSearchParams): Promise<HonuaStacItemCollectionResponse>;
45
+ private fetchDoc;
46
+ /**
47
+ * Breadth-first walk collecting item documents. Descends `rel="child"`
48
+ * links; a `collections` filter prunes Collection subtrees whose `id`
49
+ * is not requested. Every attempted document, traversal depth, per-document
50
+ * link list, response body, redirect, and origin is bounded by the locator's
51
+ * admitted policy.
52
+ */
53
+ private collectItems;
54
+ }
55
+ //# sourceMappingURL=stac-static.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stac-static.d.ts","sourceRoot":"","sources":["../../../src/core/stac-static.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,KAAK,EAAE,+BAA+B,EAAyB,MAAM,YAAY,CAAC;AAEzF,gEAAgE;AAChE,MAAM,WAAW,sBAAsB;IACrC,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,IAAI,CAAC,EAAE,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AA6CD;;;;;GAKG;AACH,qBAAa,sBAAsB;IACjC,SAAgB,MAAM,EAAE,WAAW,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;gBAE7B,MAAM,EAAE,WAAW,EAAE,OAAO,SAAK,EAAE,MAAM,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC;IAM1F;;;OAGG;IACU,MAAM,CAAC,MAAM,GAAE,sBAA2B,GAAG,OAAO,CAAC,+BAA+B,CAAC;YAcpF,QAAQ;IA0BtB;;;;;;OAMG;YACW,YAAY;CAkE3B"}