@honua/react 0.1.2-beta.0 → 0.1.4-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 (281) hide show
  1. package/contract/discovery.d.ts +34 -0
  2. package/contract/discovery.d.ts.map +1 -1
  3. package/contract/index.d.ts +7 -5
  4. package/contract/index.d.ts.map +1 -1
  5. package/contract/index.js +3 -2
  6. package/contract/pmtiles.d.ts +10 -1
  7. package/contract/pmtiles.d.ts.map +1 -1
  8. package/contract/pmtiles.js +10 -2
  9. package/contract/protocol-module.d.ts +84 -9
  10. package/contract/protocol-module.d.ts.map +1 -1
  11. package/contract/query-filter-fes.d.ts +18 -0
  12. package/contract/query-filter-fes.d.ts.map +1 -0
  13. package/contract/query-filter-fes.js +122 -0
  14. package/contract/query-filter.d.ts +300 -0
  15. package/contract/query-filter.d.ts.map +1 -0
  16. package/contract/query-filter.js +883 -0
  17. package/contract/schema.d.ts +12 -0
  18. package/contract/schema.d.ts.map +1 -1
  19. package/contract/schema.js +34 -0
  20. package/contract/source-capability-support.d.ts.map +1 -1
  21. package/contract/source-capability-support.js +15 -3
  22. package/contract/source.d.ts +45 -25
  23. package/contract/source.d.ts.map +1 -1
  24. package/contract/source.js +719 -479
  25. package/contract/types.d.ts +87 -18
  26. package/contract/types.d.ts.map +1 -1
  27. package/contract/widget-source.d.ts.map +1 -1
  28. package/core/client.d.ts +45 -21
  29. package/core/client.d.ts.map +1 -1
  30. package/core/client.js +224 -46
  31. package/core/error-classifications.d.ts +6 -0
  32. package/core/error-classifications.d.ts.map +1 -1
  33. package/core/error-classifications.js +6 -0
  34. package/core/error-code-registry.d.ts +6 -0
  35. package/core/error-code-registry.d.ts.map +1 -1
  36. package/core/error-code-registry.js +6 -0
  37. package/core/error-envelope.js +2 -0
  38. package/core/errors.d.ts +1 -1
  39. package/core/errors.js +1 -1
  40. package/core/geoparquet-sql.d.ts +68 -4
  41. package/core/geoparquet-sql.d.ts.map +1 -1
  42. package/core/geoparquet-sql.js +325 -8
  43. package/core/odata-write-codec.d.ts.map +1 -1
  44. package/core/odata-write-codec.js +0 -1
  45. package/core/odata.d.ts +6 -0
  46. package/core/odata.d.ts.map +1 -1
  47. package/core/odata.js +6 -1
  48. package/core/ogc-processes.d.ts +182 -25
  49. package/core/ogc-processes.d.ts.map +1 -1
  50. package/core/ogc-processes.js +602 -30
  51. package/core/process-runner.d.ts +8 -1
  52. package/core/process-runner.d.ts.map +1 -1
  53. package/core/process-runner.js +1 -0
  54. package/core/protocol-transport.d.ts +2 -0
  55. package/core/protocol-transport.d.ts.map +1 -1
  56. package/core/stac.d.ts +31 -0
  57. package/core/stac.d.ts.map +1 -1
  58. package/core/stac.js +136 -19
  59. package/core/surfaces.d.ts.map +1 -1
  60. package/core/surfaces.js +273 -68
  61. package/core/types.d.ts +123 -9
  62. package/core/types.d.ts.map +1 -1
  63. package/core/wfs-axis-order.d.ts +18 -0
  64. package/core/wfs-axis-order.d.ts.map +1 -0
  65. package/core/wfs-axis-order.js +108 -0
  66. package/core/wfs-capabilities.d.ts +65 -24
  67. package/core/wfs-capabilities.d.ts.map +1 -1
  68. package/core/wfs-capabilities.js +237 -27
  69. package/core/wfs-filter.d.ts +26 -3
  70. package/core/wfs-filter.d.ts.map +1 -1
  71. package/core/wfs-filter.js +48 -53
  72. package/core/wfs-protocol-error.d.ts +12 -0
  73. package/core/wfs-protocol-error.d.ts.map +1 -0
  74. package/core/wfs-protocol-error.js +13 -0
  75. package/core/wfs.d.ts +53 -1
  76. package/core/wfs.d.ts.map +1 -1
  77. package/core/wfs.js +251 -29
  78. package/core/wms-feature-info.d.ts +92 -0
  79. package/core/wms-feature-info.d.ts.map +1 -0
  80. package/core/wms-feature-info.js +285 -0
  81. package/core/wms.d.ts +9 -0
  82. package/core/wms.d.ts.map +1 -1
  83. package/core/wms.js +17 -5
  84. package/esri-compat/event-bus.d.ts +20 -0
  85. package/esri-compat/event-bus.d.ts.map +1 -1
  86. package/esri-compat/feature-filter.d.ts +46 -1
  87. package/esri-compat/feature-filter.d.ts.map +1 -1
  88. package/esri-compat/feature-filter.js +49 -0
  89. package/esri-compat/geojson-layer.d.ts +4 -2
  90. package/esri-compat/geojson-layer.d.ts.map +1 -1
  91. package/esri-compat/geojson-layer.js +4 -2
  92. package/esri-compat/identity-manager.js +2 -2
  93. package/esri-compat/imagery-layer.d.ts +2 -1
  94. package/esri-compat/imagery-layer.d.ts.map +1 -1
  95. package/esri-compat/imagery-layer.js +2 -1
  96. package/esri-compat/layer-list.d.ts +8 -1
  97. package/esri-compat/layer-list.d.ts.map +1 -1
  98. package/esri-compat/layer-list.js +11 -4
  99. package/esri-compat/legend.d.ts.map +1 -1
  100. package/esri-compat/legend.js +1 -1
  101. package/esri-compat/locator.d.ts +297 -0
  102. package/esri-compat/locator.d.ts.map +1 -0
  103. package/esri-compat/locator.js +579 -0
  104. package/esri-compat/map-image-layer.d.ts.map +1 -1
  105. package/esri-compat/map-view.d.ts.map +1 -1
  106. package/esri-compat/map-view.js +1 -1
  107. package/esri-compat/scene-view.d.ts.map +1 -1
  108. package/esri-compat/time-slider.d.ts +29 -0
  109. package/esri-compat/time-slider.d.ts.map +1 -1
  110. package/esri-compat/time-slider.js +117 -0
  111. package/esri-compat/wfs-layer.d.ts +2 -1
  112. package/esri-compat/wfs-layer.d.ts.map +1 -1
  113. package/esri-compat/wfs-layer.js +2 -1
  114. package/esri-compat/widget-host.d.ts +42 -6
  115. package/esri-compat/widget-host.d.ts.map +1 -1
  116. package/esri-compat/widget-host.js +99 -10
  117. package/generated-app/projection.d.ts.map +1 -1
  118. package/generated-app/runtime.d.ts.map +1 -1
  119. package/map/data-to-map-bridge.d.ts +1 -1
  120. package/map/data-to-map-bridge.d.ts.map +1 -1
  121. package/map/data-to-map-bridge.js +1 -2
  122. package/map/honua-map.d.ts.map +1 -1
  123. package/map/honua-map.js +1 -1
  124. package/map/index.d.ts +2 -0
  125. package/map/index.d.ts.map +1 -1
  126. package/map/index.js +2 -0
  127. package/map/realtime-reconciliation-adapter.d.ts +98 -0
  128. package/map/realtime-reconciliation-adapter.d.ts.map +1 -0
  129. package/map/realtime-reconciliation-adapter.js +84 -0
  130. package/map/temporal-playback.d.ts +25 -0
  131. package/map/temporal-playback.d.ts.map +1 -1
  132. package/map/temporal-playback.js +29 -1
  133. package/package.json +4 -3
  134. package/query-planner/canonical-filter.d.ts +30 -0
  135. package/query-planner/canonical-filter.d.ts.map +1 -0
  136. package/query-planner/canonical-filter.js +30 -0
  137. package/query-planner/columnar-plan.d.ts +63 -0
  138. package/query-planner/columnar-plan.d.ts.map +1 -0
  139. package/query-planner/columnar-plan.js +94 -0
  140. package/query-planner/diagnostics.d.ts +3 -3
  141. package/query-planner/diagnostics.d.ts.map +1 -1
  142. package/query-planner/diagnostics.js +17 -4
  143. package/query-planner/duckdb.d.ts.map +1 -1
  144. package/query-planner/duckdb.js +16 -2
  145. package/query-planner/execution-context.d.ts.map +1 -1
  146. package/query-planner/execution-context.js +3 -1
  147. package/query-planner/executor.d.ts.map +1 -1
  148. package/query-planner/executor.js +7 -1
  149. package/query-planner/geoservices.d.ts.map +1 -1
  150. package/query-planner/geoservices.js +24 -5
  151. package/query-planner/grpc.d.ts.map +1 -1
  152. package/query-planner/grpc.js +29 -5
  153. package/query-planner/index.d.ts +20 -5
  154. package/query-planner/index.d.ts.map +1 -1
  155. package/query-planner/index.js +16 -3
  156. package/query-planner/ir.d.ts +6 -1
  157. package/query-planner/ir.d.ts.map +1 -1
  158. package/query-planner/ir.js +63 -1
  159. package/query-planner/odata-protocol-module.d.ts +54 -0
  160. package/query-planner/odata-protocol-module.d.ts.map +1 -0
  161. package/query-planner/odata-protocol-module.js +199 -0
  162. package/query-planner/odata-v1.d.ts +23 -0
  163. package/query-planner/odata-v1.d.ts.map +1 -0
  164. package/query-planner/odata-v1.js +202 -0
  165. package/query-planner/odata.d.ts +0 -3
  166. package/query-planner/odata.d.ts.map +1 -1
  167. package/query-planner/odata.js +0 -143
  168. package/query-planner/ogc-features.d.ts.map +1 -1
  169. package/query-planner/ogc-features.js +23 -1
  170. package/query-planner/planner.d.ts +2 -2
  171. package/query-planner/planner.d.ts.map +1 -1
  172. package/query-planner/planner.js +146 -27
  173. package/query-planner/representation.d.ts +59 -0
  174. package/query-planner/representation.d.ts.map +1 -0
  175. package/query-planner/representation.js +140 -0
  176. package/query-planner/types.d.ts +153 -3
  177. package/query-planner/types.d.ts.map +1 -1
  178. package/query-planner/wfs-protocol-module.d.ts +57 -0
  179. package/query-planner/wfs-protocol-module.d.ts.map +1 -0
  180. package/query-planner/wfs-protocol-module.js +731 -0
  181. package/query-planner/wfs-v1.d.ts +41 -0
  182. package/query-planner/wfs-v1.d.ts.map +1 -0
  183. package/query-planner/wfs-v1.js +366 -0
  184. package/query-planner/wfs.d.ts +1 -3
  185. package/query-planner/wfs.d.ts.map +1 -1
  186. package/query-planner/wfs.js +1 -70
  187. package/react/honua-map.d.ts +3 -1
  188. package/react/honua-map.d.ts.map +1 -1
  189. package/react/honua-map.js +11 -1
  190. package/react/hooks.d.ts +1 -1
  191. package/react/hooks.js +1 -1
  192. package/react/selection.d.ts.map +1 -1
  193. package/react/selection.js +0 -0
  194. package/react/use-mounted-source.d.ts +1 -1
  195. package/react/use-mounted-source.js +1 -1
  196. package/realtime/checkpoint-store.d.ts +206 -0
  197. package/realtime/checkpoint-store.d.ts.map +1 -0
  198. package/realtime/checkpoint-store.js +504 -0
  199. package/realtime/contract.d.ts +142 -0
  200. package/realtime/contract.d.ts.map +1 -0
  201. package/realtime/contract.js +154 -0
  202. package/realtime/exploration.d.ts +16 -0
  203. package/realtime/exploration.d.ts.map +1 -0
  204. package/realtime/exploration.js +32 -0
  205. package/realtime/honua-server.d.ts +131 -0
  206. package/realtime/honua-server.d.ts.map +1 -0
  207. package/realtime/honua-server.js +302 -0
  208. package/realtime/index.d.ts +39 -0
  209. package/realtime/index.d.ts.map +1 -0
  210. package/realtime/index.js +26 -0
  211. package/realtime/odata-delta.d.ts +114 -0
  212. package/realtime/odata-delta.d.ts.map +1 -0
  213. package/realtime/odata-delta.js +483 -0
  214. package/realtime/projections.d.ts +30 -0
  215. package/realtime/projections.d.ts.map +1 -0
  216. package/realtime/projections.js +51 -0
  217. package/realtime/reconciliation.d.ts +245 -0
  218. package/realtime/reconciliation.d.ts.map +1 -0
  219. package/realtime/reconciliation.js +377 -0
  220. package/realtime/reducer.d.ts +14 -0
  221. package/realtime/reducer.d.ts.map +1 -0
  222. package/realtime/reducer.js +351 -0
  223. package/realtime/resumable-transport.d.ts +111 -0
  224. package/realtime/resumable-transport.d.ts.map +1 -0
  225. package/realtime/resumable-transport.js +406 -0
  226. package/realtime/resumable.d.ts +104 -0
  227. package/realtime/resumable.d.ts.map +1 -0
  228. package/realtime/resumable.js +632 -0
  229. package/realtime/sse.d.ts +23 -0
  230. package/realtime/sse.d.ts.map +1 -0
  231. package/realtime/sse.js +147 -0
  232. package/realtime/store.d.ts +18 -0
  233. package/realtime/store.d.ts.map +1 -0
  234. package/realtime/store.js +63 -0
  235. package/realtime/types.d.ts +190 -0
  236. package/realtime/types.d.ts.map +1 -0
  237. package/realtime/types.js +10 -0
  238. package/realtime/websocket.d.ts +60 -0
  239. package/realtime/websocket.d.ts.map +1 -0
  240. package/realtime/websocket.js +157 -0
  241. package/realtime/wire.d.ts +28 -0
  242. package/realtime/wire.d.ts.map +1 -0
  243. package/realtime/wire.js +73 -0
  244. package/runtime/index.d.ts +6 -2
  245. package/runtime/index.d.ts.map +1 -1
  246. package/runtime/index.js +3 -1
  247. package/runtime/load-package.d.ts +24 -0
  248. package/runtime/load-package.d.ts.map +1 -1
  249. package/runtime/load-package.js +45 -1
  250. package/runtime/maplibre-renderer.d.ts +11 -0
  251. package/runtime/maplibre-renderer.d.ts.map +1 -1
  252. package/runtime/maplibre-renderer.js +32 -7
  253. package/runtime/offline-region-protocol.d.ts +73 -0
  254. package/runtime/offline-region-protocol.d.ts.map +1 -0
  255. package/runtime/offline-region-protocol.js +63 -0
  256. package/runtime/offline-region-style.d.ts +78 -0
  257. package/runtime/offline-region-style.d.ts.map +1 -0
  258. package/runtime/offline-region-style.js +147 -0
  259. package/runtime/pmtiles-protocol.d.ts +7 -8
  260. package/runtime/pmtiles-protocol.d.ts.map +1 -1
  261. package/runtime/pmtiles-protocol.js +19 -66
  262. package/runtime/protocol-registry.d.ts +55 -0
  263. package/runtime/protocol-registry.d.ts.map +1 -0
  264. package/runtime/protocol-registry.js +103 -0
  265. package/runtime/runtime.d.ts +2 -0
  266. package/runtime/runtime.d.ts.map +1 -1
  267. package/runtime/runtime.js +6 -1
  268. package/studio/index.d.ts +24 -7
  269. package/studio/index.d.ts.map +1 -1
  270. package/studio/index.js +21 -7
  271. package/studio/lifecycle-client.d.ts +164 -0
  272. package/studio/lifecycle-client.d.ts.map +1 -0
  273. package/studio/lifecycle-client.js +299 -0
  274. package/studio/lifecycle-errors.d.ts +91 -0
  275. package/studio/lifecycle-errors.d.ts.map +1 -0
  276. package/studio/lifecycle-errors.js +77 -0
  277. package/studio/lifecycle-types.d.ts +321 -0
  278. package/studio/lifecycle-types.d.ts.map +1 -0
  279. package/studio/lifecycle-types.js +22 -0
  280. package/webmap/convert-label.js +0 -1
  281. package/webmap/convert-symbol.d.ts.map +1 -1
@@ -0,0 +1,13 @@
1
+ import { HonuaSdkError } from "./error-envelope.js";
2
+ /** Typed, credential-safe fail-closed WFS protocol error. */
3
+ export class HonuaWfsProtocolError extends HonuaSdkError {
4
+ reason;
5
+ constructor(reason, message, options = {}) {
6
+ super("query.execution.wfs-protocol", message, {
7
+ context: { reason },
8
+ ...("cause" in options ? { cause: options.cause } : {}),
9
+ });
10
+ this.reason = reason;
11
+ this.name = "HonuaWfsProtocolError";
12
+ }
13
+ }
package/core/wfs.d.ts CHANGED
@@ -50,9 +50,10 @@ export declare class HonuaWfs {
50
50
  readonly version: string;
51
51
  /** Counter exposed for tests / diagnostics: how many times capabilities was fetched. */
52
52
  capabilitiesFetches: number;
53
- private capabilitiesPromise;
54
53
  private rawCapabilitiesXml;
55
54
  private resolvedSnapshot;
55
+ /** Resolved geometry property per feature type; shares the metadata cache lifecycle. */
56
+ private readonly geometryPropertyNames;
56
57
  constructor(options: HonuaWfsOptions);
57
58
  /**
58
59
  * Fetch and cache the GetCapabilities document. Subsequent calls reuse the
@@ -63,6 +64,33 @@ export declare class HonuaWfs {
63
64
  }): Promise<WfsCapabilitiesSnapshot>;
64
65
  /** Discard the cached capabilities snapshot so the next call re-fetches. */
65
66
  refresh(): void;
67
+ /**
68
+ * Fetch the `DescribeFeatureType` XSD for one feature type. Returned raw so
69
+ * `Source.protocol("wfs")` callers can read schema detail the canonical
70
+ * surface does not model.
71
+ */
72
+ describeFeatureType(typeName: string, options?: {
73
+ signal?: AbortSignal;
74
+ }): Promise<{
75
+ text: string;
76
+ contentType: string;
77
+ }>;
78
+ /**
79
+ * Resolve the geometry property name of one feature type from its
80
+ * `DescribeFeatureType` schema, caching the result alongside the
81
+ * capabilities snapshot. Fails closed with
82
+ * `HonuaWfsProtocolError("unresolved-geometry-property")` rather than
83
+ * assuming a vendor default: `the_geom` is only the PostGIS-via-GeoServer
84
+ * convention, MapServer serves `msGeometry`, and other servers use
85
+ * per-schema names, so guessing silently matches nothing.
86
+ *
87
+ * Feature types that declare several geometry properties resolve to the
88
+ * first declared one (the server's default geometry); pin a different one
89
+ * with `locator.geometryName`.
90
+ */
91
+ geometryPropertyName(typeName: string, options?: {
92
+ signal?: AbortSignal;
93
+ }): Promise<string>;
66
94
  /**
67
95
  * Resolve the concrete request URL for a WFS operation, honouring the
68
96
  * DCP `xlink:href` a raw server advertises in GetCapabilities (e.g.
@@ -94,6 +122,7 @@ export declare class HonuaWfs {
94
122
  contentType?: string;
95
123
  body?: string;
96
124
  signal?: AbortSignal;
125
+ maxResponseBytes?: number;
97
126
  }): Promise<{
98
127
  text: string;
99
128
  contentType: string;
@@ -120,6 +149,21 @@ export declare class HonuaWfsFeatureType {
120
149
  capabilities(options?: {
121
150
  signal?: AbortSignal;
122
151
  }): Promise<WfsCapabilitiesSnapshot>;
152
+ /** Raw `DescribeFeatureType` XSD for the bound type name. */
153
+ describeFeatureType(options?: {
154
+ signal?: AbortSignal;
155
+ }): Promise<{
156
+ text: string;
157
+ contentType: string;
158
+ }>;
159
+ /**
160
+ * Geometry property name of the bound feature type, resolved from
161
+ * `DescribeFeatureType` and cached on the root. Fails closed when the schema
162
+ * does not name one — see {@link HonuaWfs.geometryPropertyName}.
163
+ */
164
+ geometryPropertyName(options?: {
165
+ signal?: AbortSignal;
166
+ }): Promise<string>;
123
167
  /**
124
168
  * Issue a GetFeature request. Returns parsed JSON when the negotiated
125
169
  * output format is JSON; otherwise returns the raw body as a string for
@@ -137,6 +181,10 @@ export declare class HonuaWfsFeatureType {
137
181
  outputFormat?: string;
138
182
  method?: "GET" | "POST";
139
183
  body?: string;
184
+ namespace?: {
185
+ readonly prefix: string;
186
+ readonly uri: string;
187
+ };
140
188
  signal?: AbortSignal;
141
189
  }): Promise<{
142
190
  kind: "json";
@@ -176,6 +224,10 @@ export declare class HonuaWfsFeatureType {
176
224
  count?: number;
177
225
  startIndex?: number;
178
226
  outputFormat?: string;
227
+ namespace?: {
228
+ readonly prefix: string;
229
+ readonly uri: string;
230
+ };
179
231
  }): string;
180
232
  }
181
233
  interface HonuaWfsStoredQueryOptions {
package/core/wfs.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"wfs.d.ts","sourceRoot":"","sources":["../../../src/core/wfs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,OAAO,EACL,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAK3B,MAAM,uBAAuB,CAAC;AA2B/B;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,WAAW,CAAC;IACpB,kEAAkE;IAClE,WAAW,EAAE,MAAM,CAAC;IACpB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,qBAAa,QAAQ;IACnB,SAAgB,MAAM,EAAE,WAAW,CAAC;IACpC,SAAgB,WAAW,EAAE,MAAM,CAAC;IACpC,SAAgB,OAAO,EAAE,MAAM,CAAC;IAEhC,wFAAwF;IACjF,mBAAmB,SAAK;IAE/B,OAAO,CAAC,mBAAmB,CAA+C;IAC1E,OAAO,CAAC,kBAAkB,CAAqB;IAC/C,OAAO,CAAC,gBAAgB,CAAsC;gBAE3C,OAAO,EAAE,eAAe;IAM3C;;;OAGG;IACI,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAWzF,4EAA4E;IACrE,OAAO,IAAI,IAAI;IAMtB;;;;;;;;;;OAUG;IACI,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM;IAMtE,2EAA2E;IACpE,eAAe,IAAI,MAAM,GAAG,SAAS;IAI5C,oDAAoD;IAC7C,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,mBAAmB;IAIzD;;;;OAIG;IACU,aAAa,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,SAAS,MAAM,EAAE,CAAC;IAYnF,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,mBAAmB;IAInD,mEAAmE;IACtD,WAAW,CACtB,MAAM,EAAE,KAAK,GAAG,MAAM,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GACrF,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAcjE,0DAA0D;IACnD,qBAAqB,CAAC,QAAQ,EAAE,uBAAuB,GAAG,kBAAkB,GAAG,SAAS;YAoBjF,iBAAiB;CAgBhC;AAcD,UAAU,0BAA0B;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,qBAAa,mBAAmB;IAC9B,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAEd,OAAO,EAAE,0BAA0B;IAKtD,8DAA8D;IACvD,YAAY,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,uBAAuB,CAAC;IAIzF;;;;OAIG;IACU,UAAU,CAAC,MAAM,EAAE;QAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;QAChC,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QACxB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,OAAO,CACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAC1G;IA4CD;;;OAGG;IACU,gBAAgB,CAAC,MAAM,EAAE;QACpC,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAqBlD;;;OAGG;IACU,WAAW,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAWxG,4EAA4E;IACrE,kBAAkB,CAAC,MAAM,EAAE;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,MAAM;CAcX;AAED,UAAU,0BAA0B;IAClC,IAAI,EAAE,QAAQ,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,SAAgB,IAAI,EAAE,QAAQ,CAAC;IAC/B,SAAgB,EAAE,EAAE,MAAM,CAAC;gBAER,OAAO,EAAE,0BAA0B;IAKtD,8EAA8E;IACjE,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAiBzG;;;;;OAKG;IACU,OAAO,CAAC,MAAM,EAAE;QAC3B,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;QACvD,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,MAAM,CAAC,EAAE,WAAW,CAAC;KACtB,GAAG,OAAO,CACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,KAAK,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAC1G;CAgCF;AAID,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM,CAKxE;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAIpF;AAED,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGnF;AAWD;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAYrE"}
1
+ {"version":3,"file":"wfs.d.ts","sourceRoot":"","sources":["../../../src/core/wfs.ts"],"names":[],"mappings":"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"}
package/core/wfs.js CHANGED
@@ -18,10 +18,13 @@
18
18
  *
19
19
  * @module
20
20
  */
21
- import { HonuaHttpError, HonuaWfsExceptionError } from "./errors.js";
22
- import { parseListStoredQueriesResponse, parseWfsCapabilities, parseWfsExceptionReport, parseWfsTransactionResponse, } from "./wfs-capabilities.js";
21
+ import { HonuaAbortError, HonuaHttpError, HonuaWfsExceptionError } from "./errors.js";
22
+ import { parseListStoredQueriesResponse, parseWfsCapabilities, parseWfsDescribeFeatureTypeGeometry, parseWfsExceptionReport, parseWfsTransactionResponse, } from "./wfs-capabilities.js";
23
+ import { HonuaWfsProtocolError } from "./wfs-protocol-error.js";
23
24
  const DEFAULT_VERSION = "2.0.0";
24
25
  const SERVICE_PARAM = "WFS";
26
+ const WFS_METADATA_MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
27
+ const WFS_FEATURE_MAX_RESPONSE_BYTES = 32 * 1024 * 1024;
25
28
  /** Output formats (lower-cased) the canonical adapter treats as JSON. */
26
29
  const JSON_OUTPUT_FORMATS = new Set([
27
30
  "application/json",
@@ -42,6 +45,7 @@ const GML_OUTPUT_FORMATS = new Set([
42
45
  "text/xml; subtype=gml/3.2.1",
43
46
  "text/xml;subtype=gml/3.2.1",
44
47
  ]);
48
+ const CAPABILITIES_STATES = new WeakMap();
45
49
  /**
46
50
  * Root WFS handle. Holds the capabilities cache and exposes feature-type /
47
51
  * stored-query factories.
@@ -52,33 +56,129 @@ export class HonuaWfs {
52
56
  version;
53
57
  /** Counter exposed for tests / diagnostics: how many times capabilities was fetched. */
54
58
  capabilitiesFetches = 0;
55
- capabilitiesPromise;
56
59
  rawCapabilitiesXml;
57
60
  resolvedSnapshot;
61
+ /** Resolved geometry property per feature type; shares the metadata cache lifecycle. */
62
+ geometryPropertyNames = new Map();
58
63
  constructor(options) {
59
64
  this.client = options.client;
60
65
  this.endpointUrl = options.endpointUrl;
61
66
  this.version = options.version ?? DEFAULT_VERSION;
67
+ CAPABILITIES_STATES.set(this, { generation: 0 });
62
68
  }
63
69
  /**
64
70
  * Fetch and cache the GetCapabilities document. Subsequent calls reuse the
65
71
  * parsed snapshot. Throws `HonuaWfsExceptionError` on `<ows:ExceptionReport>`.
66
72
  */
67
- capabilities(options) {
68
- if (!this.capabilitiesPromise) {
69
- this.capabilitiesPromise = this.fetchCapabilities(options).catch((err) => {
70
- // Allow retry after a transient failure.
71
- this.capabilitiesPromise = undefined;
72
- throw err;
73
+ async capabilities(options) {
74
+ if (options?.signal?.aborted)
75
+ throw new HonuaAbortError();
76
+ if (this.resolvedSnapshot)
77
+ return this.resolvedSnapshot;
78
+ const state = capabilitiesState(this);
79
+ const generation = state.generation;
80
+ let flight = state.flight;
81
+ if (!flight || flight.generation !== generation) {
82
+ const identity = {};
83
+ const controller = new AbortController();
84
+ const promise = this.fetchCapabilities({ signal: controller.signal }).then((fetched) => {
85
+ // A refresh advances the generation. An older response may still
86
+ // settle after a transport ignores abort, but it must never repopulate
87
+ // the cache or become evidence for the new generation.
88
+ if (state.generation === generation && state.flight?.identity === identity) {
89
+ this.rawCapabilitiesXml = fetched.xml;
90
+ this.resolvedSnapshot = fetched.snapshot;
91
+ }
92
+ return fetched.snapshot;
93
+ });
94
+ const nextFlight = {
95
+ generation,
96
+ identity,
97
+ controller,
98
+ promise,
99
+ subscribers: 0,
100
+ settled: false,
101
+ };
102
+ flight = nextFlight;
103
+ state.flight = nextFlight;
104
+ void promise.then(() => {
105
+ nextFlight.settled = true;
106
+ if (state.flight === nextFlight)
107
+ state.flight = undefined;
108
+ }, () => {
109
+ nextFlight.settled = true;
110
+ if (state.flight === nextFlight)
111
+ state.flight = undefined;
73
112
  });
74
113
  }
75
- return this.capabilitiesPromise;
114
+ return subscribeCapabilitiesFlight(state, flight, options?.signal);
76
115
  }
77
116
  /** Discard the cached capabilities snapshot so the next call re-fetches. */
78
117
  refresh() {
79
- this.capabilitiesPromise = undefined;
118
+ const state = capabilitiesState(this);
119
+ state.generation += 1;
120
+ const staleFlight = state.flight;
121
+ state.flight = undefined;
80
122
  this.rawCapabilitiesXml = undefined;
81
123
  this.resolvedSnapshot = undefined;
124
+ this.geometryPropertyNames.clear();
125
+ if (staleFlight && !staleFlight.settled)
126
+ staleFlight.controller.abort();
127
+ }
128
+ /**
129
+ * Fetch the `DescribeFeatureType` XSD for one feature type. Returned raw so
130
+ * `Source.protocol("wfs")` callers can read schema detail the canonical
131
+ * surface does not model.
132
+ */
133
+ async describeFeatureType(typeName, options) {
134
+ const params = new URLSearchParams({
135
+ service: SERVICE_PARAM,
136
+ version: this.version,
137
+ request: "DescribeFeatureType",
138
+ typeNames: typeName,
139
+ });
140
+ const requestOptions = {
141
+ accept: "application/xml, text/xml",
142
+ maxResponseBytes: WFS_METADATA_MAX_RESPONSE_BYTES,
143
+ };
144
+ if (options?.signal)
145
+ requestOptions.signal = options.signal;
146
+ const { text, contentType } = await this.requestText("GET", appendQuery(this.operationUrl("DescribeFeatureType", "GET"), params), requestOptions);
147
+ return { text, contentType };
148
+ }
149
+ /**
150
+ * Resolve the geometry property name of one feature type from its
151
+ * `DescribeFeatureType` schema, caching the result alongside the
152
+ * capabilities snapshot. Fails closed with
153
+ * `HonuaWfsProtocolError("unresolved-geometry-property")` rather than
154
+ * assuming a vendor default: `the_geom` is only the PostGIS-via-GeoServer
155
+ * convention, MapServer serves `msGeometry`, and other servers use
156
+ * per-schema names, so guessing silently matches nothing.
157
+ *
158
+ * Feature types that declare several geometry properties resolve to the
159
+ * first declared one (the server's default geometry); pin a different one
160
+ * with `locator.geometryName`.
161
+ */
162
+ async geometryPropertyName(typeName, options) {
163
+ const cached = this.geometryPropertyNames.get(typeName);
164
+ if (cached !== undefined)
165
+ return cached;
166
+ let candidates;
167
+ try {
168
+ const { text } = await this.describeFeatureType(typeName, options);
169
+ candidates = parseWfsDescribeFeatureTypeGeometry(text, typeName);
170
+ }
171
+ catch (error) {
172
+ if (error instanceof HonuaAbortError)
173
+ throw error;
174
+ throw new HonuaWfsProtocolError("unresolved-geometry-property", `WFS DescribeFeatureType could not resolve the geometry property of feature type "${typeName}"; set locator.geometryName to name it explicitly`, { cause: error });
175
+ }
176
+ const resolved = candidates[0];
177
+ if (resolved === undefined) {
178
+ throw new HonuaWfsProtocolError("unresolved-geometry-property", `WFS DescribeFeatureType declares no geometry property for feature type "${typeName}"; set locator.geometryName to name it explicitly`);
179
+ }
180
+ this.geometryPropertyNames.set(typeName, resolved);
181
+ return resolved;
82
182
  }
83
183
  /**
84
184
  * Resolve the concrete request URL for a WFS operation, honouring the
@@ -115,7 +215,10 @@ export class HonuaWfs {
115
215
  version: this.version,
116
216
  request: "ListStoredQueries",
117
217
  });
118
- const requestOptions = { accept: "application/xml, text/xml" };
218
+ const requestOptions = {
219
+ accept: "application/xml, text/xml",
220
+ maxResponseBytes: WFS_METADATA_MAX_RESPONSE_BYTES,
221
+ };
119
222
  if (options?.signal)
120
223
  requestOptions.signal = options.signal;
121
224
  const { text } = await this.requestText("GET", appendQuery(this.endpointUrl, params), requestOptions);
@@ -129,6 +232,7 @@ export class HonuaWfs {
129
232
  try {
130
233
  const requestOptions = {
131
234
  accept: options.accept,
235
+ maxResponseBytes: options.maxResponseBytes ?? WFS_METADATA_MAX_RESPONSE_BYTES,
132
236
  };
133
237
  if (options.contentType !== undefined)
134
238
  requestOptions.contentType = options.contentType;
@@ -146,11 +250,11 @@ export class HonuaWfs {
146
250
  negotiateOutputFormat(snapshot) {
147
251
  const formats = snapshot.outputFormatsByOp.get("GetFeature") ?? [];
148
252
  for (const format of formats) {
149
- if (JSON_OUTPUT_FORMATS.has(format))
253
+ if (JSON_OUTPUT_FORMATS.has(format.toLowerCase()))
150
254
  return { kind: "json", format };
151
255
  }
152
256
  for (const format of formats) {
153
- if (GML_OUTPUT_FORMATS.has(format))
257
+ if (GML_OUTPUT_FORMATS.has(format.toLowerCase()))
154
258
  return { kind: "gml", format };
155
259
  }
156
260
  if (formats.length === 0) {
@@ -171,25 +275,116 @@ export class HonuaWfs {
171
275
  version: this.version,
172
276
  request: "GetCapabilities",
173
277
  });
174
- const requestOptions = { accept: "application/xml, text/xml" };
278
+ const requestOptions = {
279
+ accept: "application/xml, text/xml",
280
+ maxResponseBytes: WFS_METADATA_MAX_RESPONSE_BYTES,
281
+ };
175
282
  if (options?.signal)
176
283
  requestOptions.signal = options.signal;
177
284
  const { text } = await this.requestText("GET", appendQuery(this.endpointUrl, params), requestOptions);
178
- this.rawCapabilitiesXml = text;
179
- const snapshot = parseWfsCapabilities(text);
180
- canonicalizeOperationUrls(snapshot, this.endpointUrl, this.client.serverBaseUrl);
181
- this.resolvedSnapshot = snapshot;
182
- return snapshot;
285
+ const snapshot = canonicalizeOperationUrls(parseWfsCapabilities(text), this.endpointUrl, this.client.serverBaseUrl);
286
+ return { snapshot, xml: text };
183
287
  }
184
288
  }
289
+ function capabilitiesState(root) {
290
+ const state = CAPABILITIES_STATES.get(root);
291
+ if (!state)
292
+ throw new TypeError("WFS capabilities state is unavailable");
293
+ return state;
294
+ }
295
+ function subscribeCapabilitiesFlight(state, flight, signal) {
296
+ flight.subscribers += 1;
297
+ return new Promise((resolve, reject) => {
298
+ let finished = false;
299
+ const finish = () => {
300
+ if (finished)
301
+ return false;
302
+ finished = true;
303
+ signal?.removeEventListener("abort", onCallerAbort);
304
+ flight.controller.signal.removeEventListener("abort", onGenerationAbort);
305
+ flight.subscribers -= 1;
306
+ return true;
307
+ };
308
+ const abortOrphanedFlight = () => {
309
+ if (flight.settled || flight.subscribers !== 0 || flight.controller.signal.aborted)
310
+ return;
311
+ if (state.flight === flight)
312
+ state.flight = undefined;
313
+ flight.controller.abort();
314
+ };
315
+ const onCallerAbort = () => {
316
+ if (!finish())
317
+ return;
318
+ reject(new HonuaAbortError());
319
+ abortOrphanedFlight();
320
+ };
321
+ const onGenerationAbort = () => {
322
+ if (!finish())
323
+ return;
324
+ reject(new HonuaAbortError("WFS capabilities discovery was invalidated"));
325
+ };
326
+ signal?.addEventListener("abort", onCallerAbort, { once: true });
327
+ flight.controller.signal.addEventListener("abort", onGenerationAbort, { once: true });
328
+ if (signal?.aborted)
329
+ onCallerAbort();
330
+ else if (flight.controller.signal.aborted)
331
+ onGenerationAbort();
332
+ flight.promise.then((snapshot) => {
333
+ if (!finish())
334
+ return;
335
+ resolve(snapshot);
336
+ }, (error) => {
337
+ if (!finish())
338
+ return;
339
+ reject(error);
340
+ });
341
+ });
342
+ }
185
343
  function canonicalizeOperationUrls(snapshot, endpointUrl, clientBaseUrl) {
186
344
  const capabilitiesEndpoint = new URL(endpointUrl, clientBaseUrl);
187
- for (const operation of snapshot.operations.values()) {
188
- if (operation.getUrl)
189
- operation.getUrl = new URL(operation.getUrl, capabilitiesEndpoint).toString();
190
- if (operation.postUrl)
191
- operation.postUrl = new URL(operation.postUrl, capabilitiesEndpoint).toString();
192
- }
345
+ const operations = new Map([...snapshot.operations].map(([name, operation]) => [
346
+ name,
347
+ Object.freeze({
348
+ ...operation,
349
+ ...(operation.getUrl ? { getUrl: new URL(operation.getUrl, capabilitiesEndpoint).toString() } : {}),
350
+ ...(operation.postUrl ? { postUrl: new URL(operation.postUrl, capabilitiesEndpoint).toString() } : {}),
351
+ }),
352
+ ]));
353
+ return Object.freeze({
354
+ ...snapshot,
355
+ operations: immutableWfsMap(operations),
356
+ });
357
+ }
358
+ function immutableWfsMap(source) {
359
+ const owned = new Map(source);
360
+ const view = {
361
+ get size() {
362
+ return owned.size;
363
+ },
364
+ get(key) {
365
+ return owned.get(key);
366
+ },
367
+ has(key) {
368
+ return owned.has(key);
369
+ },
370
+ forEach(callbackfn, thisArg) {
371
+ for (const [key, value] of owned)
372
+ callbackfn.call(thisArg, value, key, view);
373
+ },
374
+ entries() {
375
+ return owned.entries();
376
+ },
377
+ keys() {
378
+ return owned.keys();
379
+ },
380
+ values() {
381
+ return owned.values();
382
+ },
383
+ [Symbol.iterator]() {
384
+ return owned[Symbol.iterator]();
385
+ },
386
+ };
387
+ return Object.freeze(view);
193
388
  }
194
389
  /**
195
390
  * Per-feature-type WFS surface. Implements the wire methods that the
@@ -207,6 +402,18 @@ export class HonuaWfsFeatureType {
207
402
  capabilities(options) {
208
403
  return this.root.capabilities(options);
209
404
  }
405
+ /** Raw `DescribeFeatureType` XSD for the bound type name. */
406
+ describeFeatureType(options) {
407
+ return this.root.describeFeatureType(this.typeName, options);
408
+ }
409
+ /**
410
+ * Geometry property name of the bound feature type, resolved from
411
+ * `DescribeFeatureType` and cached on the root. Fails closed when the schema
412
+ * does not name one — see {@link HonuaWfs.geometryPropertyName}.
413
+ */
414
+ geometryPropertyName(options) {
415
+ return this.root.geometryPropertyName(this.typeName, options);
416
+ }
210
417
  /**
211
418
  * Issue a GetFeature request. Returns parsed JSON when the negotiated
212
419
  * output format is JSON; otherwise returns the raw body as a string for
@@ -215,7 +422,10 @@ export class HonuaWfsFeatureType {
215
422
  async getFeature(params) {
216
423
  const method = params.method ?? "GET";
217
424
  const accept = params.outputFormat ?? "application/geo+json, application/json;q=0.9, application/xml;q=0.5";
218
- const requestOptions = { accept };
425
+ const requestOptions = {
426
+ accept,
427
+ maxResponseBytes: WFS_FEATURE_MAX_RESPONSE_BYTES,
428
+ };
219
429
  if (params.signal)
220
430
  requestOptions.signal = params.signal;
221
431
  let response;
@@ -231,6 +441,9 @@ export class HonuaWfsFeatureType {
231
441
  request: "GetFeature",
232
442
  typeNames: this.typeName,
233
443
  });
444
+ if (params.namespace !== undefined) {
445
+ search.set("NAMESPACES", `xmlns(${params.namespace.prefix},${params.namespace.uri})`);
446
+ }
234
447
  if (params.filter !== undefined)
235
448
  search.set("filter", params.filter);
236
449
  if (params.bbox !== undefined)
@@ -279,7 +492,10 @@ export class HonuaWfsFeatureType {
279
492
  search.set("count", String(params.count));
280
493
  if (typeof params.startIndex === "number")
281
494
  search.set("startIndex", String(params.startIndex));
282
- const requestOptions = { accept: "application/xml, text/xml" };
495
+ const requestOptions = {
496
+ accept: "application/xml, text/xml",
497
+ maxResponseBytes: WFS_FEATURE_MAX_RESPONSE_BYTES,
498
+ };
283
499
  if (params.signal)
284
500
  requestOptions.signal = params.signal;
285
501
  const { text, contentType } = await this.root.requestText("GET", appendQuery(this.root.endpointUrl, search), requestOptions);
@@ -318,6 +534,9 @@ export class HonuaWfsFeatureType {
318
534
  search.set("startIndex", String(params.startIndex));
319
535
  if (params.outputFormat !== undefined)
320
536
  search.set("outputFormat", params.outputFormat);
537
+ if (params.namespace !== undefined) {
538
+ search.set("NAMESPACES", `xmlns(${params.namespace.prefix},${params.namespace.uri})`);
539
+ }
321
540
  return appendQuery(this.root.endpointUrl, search);
322
541
  }
323
542
  }
@@ -370,7 +589,10 @@ export class HonuaWfsStoredQuery {
370
589
  }
371
590
  }
372
591
  const accept = params.outputFormat ?? "application/geo+json, application/json;q=0.9, application/xml;q=0.5";
373
- const requestOptions = { accept };
592
+ const requestOptions = {
593
+ accept,
594
+ maxResponseBytes: WFS_FEATURE_MAX_RESPONSE_BYTES,
595
+ };
374
596
  if (params.signal)
375
597
  requestOptions.signal = params.signal;
376
598
  const { text, contentType } = await this.root.requestText("GET", appendQuery(this.root.operationUrl("GetFeature", "GET"), search), requestOptions);
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Capabilities-driven WMS 1.3 `GetFeatureInfo` execution.
3
+ *
4
+ * The first-party path in `wms.ts` addresses Honua Server's
5
+ * `/rest/services/{id}/MapServer/WMS` alias by service id. This module
6
+ * generalizes the same wire request so it can also be issued against the
7
+ * DCP operation URL a third-party `GetCapabilities` advertises, reusing the
8
+ * shared KVP serializer (and therefore the shared WMS 1.3 axis-order rule)
9
+ * rather than restating it.
10
+ *
11
+ * Everything here is fail-closed. A format the canonical `Result` contract
12
+ * cannot represent is never selected, a CRS whose WMS 1.3 axis order the SDK
13
+ * cannot prove is never sent, and a response body that does not decode into
14
+ * features raises `HonuaCapabilityNotSupportedError` instead of degrading into
15
+ * a silently empty result.
16
+ *
17
+ * @module
18
+ */
19
+ import type { HonuaProtocolTransport } from "./protocol-transport.js";
20
+ import type { HonuaTypedFeature } from "./types.js";
21
+ import type { WmsFeatureInfoRequest } from "./wms-types.js";
22
+ /**
23
+ * Response ceiling for a point `GetFeatureInfo`. The request renders a 1×1
24
+ * image, so a conformant answer is small; the bound keeps a hostile or
25
+ * misconfigured server from turning identify-on-click into an unbounded read.
26
+ */
27
+ export declare const WMS_FEATURE_INFO_MAX_RESPONSE_BYTES: number;
28
+ /** Negotiated `INFO_FORMAT` plus the decoder family it selects. */
29
+ export interface WmsFeatureInfoFormatChoice {
30
+ readonly kind: "json" | "gml";
31
+ /** Exact spelling the service advertised, sent verbatim on the wire. */
32
+ readonly format: string;
33
+ }
34
+ /**
35
+ * Classify one advertised `INFO_FORMAT`. Returns `undefined` when the format
36
+ * carries no structure the canonical contract can project.
37
+ */
38
+ export declare function classifyWmsFeatureInfoFormat(format: string): "json" | "gml" | undefined;
39
+ /**
40
+ * Pick the `INFO_FORMAT` the canonical adapter should request from the formats
41
+ * a service advertises for `GetFeatureInfo`. JSON families win over GML; within
42
+ * a family the SDK's preference order decides, not the server's ordering, so
43
+ * the selection is deterministic across deployments.
44
+ */
45
+ export declare function selectWmsFeatureInfoFormat(advertised: readonly string[]): WmsFeatureInfoFormatChoice | undefined;
46
+ /**
47
+ * Filter a layer's advertised CRS list down to the identifiers a point
48
+ * `GetFeatureInfo` may use, preserving the advertised spelling and order.
49
+ */
50
+ export declare function reviewedWmsQueryCrs(advertised: readonly string[]): readonly string[];
51
+ /**
52
+ * Resolve the CRS a canonical query should put on the wire.
53
+ *
54
+ * The requested code comes from the spatial filter geometry (defaulting to
55
+ * `CRS:84`). An exact advertised spelling always wins. `CRS:84` and `EPSG:4326`
56
+ * are interchangeable *inputs* — both describe the same canonical `(x, y)` =
57
+ * `(lon, lat)` point and differ only in the wire axis order, which the shared
58
+ * serializer applies for whichever spelling is chosen — so a request in one is
59
+ * satisfied by the other when only that one is advertised. Anything else
60
+ * returns `undefined` so the caller can fail closed.
61
+ */
62
+ export declare function resolveWmsQueryCrs(reviewed: readonly string[], requested: string): string | undefined;
63
+ /** Reviewed, same-origin `GetFeatureInfo` operation binding. */
64
+ export interface WmsFeatureInfoBinding {
65
+ /** Absolute operation URL advertised by `GetCapabilities`. */
66
+ readonly url: string;
67
+ /** Negotiated `INFO_FORMAT`. */
68
+ readonly format: string;
69
+ }
70
+ export interface ExecuteWmsFeatureInfoOptions {
71
+ readonly binding: WmsFeatureInfoBinding;
72
+ readonly request: WmsFeatureInfoRequest;
73
+ /** Source id used for capability errors raised on an unprojectable response. */
74
+ readonly sourceId: string;
75
+ }
76
+ /**
77
+ * Issue a `GetFeatureInfo` against the capabilities-advertised operation URL
78
+ * and project the response into canonical typed features.
79
+ *
80
+ * Vendor query state already present on the advertised URL (tenant selectors,
81
+ * map identifiers) is preserved; the WMS KVP names are overwritten so a
82
+ * capabilities document cannot pin a stale `BBOX` or `INFO_FORMAT`.
83
+ */
84
+ export declare function executeWmsFeatureInfo<T = Record<string, unknown>>(transport: Pick<HonuaProtocolTransport, "requestText">, options: ExecuteWmsFeatureInfoOptions): Promise<ReadonlyArray<HonuaTypedFeature<T>>>;
85
+ /**
86
+ * Project a decoded `GetFeatureInfo` body into canonical typed features.
87
+ * `kind` is the negotiated decoder family; the observed `contentType` only
88
+ * narrows a JSON negotiation that the server answered with XML (a common
89
+ * shape for OGC `ServiceExceptionReport` bodies returned with HTTP 200).
90
+ */
91
+ export declare function decodeWmsFeatureInfoBody<T = Record<string, unknown>>(text: string, contentType: string, kind: "json" | "gml", sourceId: string): ReadonlyArray<HonuaTypedFeature<T>>;
92
+ //# sourceMappingURL=wms-feature-info.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wms-feature-info.d.ts","sourceRoot":"","sources":["../../../src/core/wms-feature-info.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAKH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAG5D;;;;GAIG;AACH,eAAO,MAAM,mCAAmC,QAAc,CAAC;AAoC/D,mEAAmE;AACnE,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAMD;;;GAGG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAKvF;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,0BAA0B,GAAG,SAAS,CAWhH;AAkBD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,MAAM,EAAE,CASpF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYrG;AAED,gEAAgE;AAChE,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,gCAAgC;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,qBAAqB,CAAC;IACxC,gFAAgF;IAChF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrE,SAAS,EAAE,IAAI,CAAC,sBAAsB,EAAE,aAAa,CAAC,EACtD,OAAO,EAAE,4BAA4B,GACpC,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAAC,CAoB9C;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,GAAG,KAAK,EACpB,QAAQ,EAAE,MAAM,GACf,aAAa,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,CAarC"}