@honua/react 0.1.2-beta.0 → 0.1.7-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) 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 +88 -19
  26. package/contract/types.d.ts.map +1 -1
  27. package/contract/types.js +4 -0
  28. package/contract/widget-source.d.ts.map +1 -1
  29. package/core/client.d.ts +51 -21
  30. package/core/client.d.ts.map +1 -1
  31. package/core/client.js +234 -54
  32. package/core/error-classifications.d.ts +23 -0
  33. package/core/error-classifications.d.ts.map +1 -1
  34. package/core/error-classifications.js +23 -0
  35. package/core/error-code-registry.d.ts +24 -1
  36. package/core/error-code-registry.d.ts.map +1 -1
  37. package/core/error-code-registry.js +23 -0
  38. package/core/error-envelope.js +2 -0
  39. package/core/errors.d.ts +2 -2
  40. package/core/errors.d.ts.map +1 -1
  41. package/core/errors.js +1 -1
  42. package/core/geoparquet-sql.d.ts +69 -5
  43. package/core/geoparquet-sql.d.ts.map +1 -1
  44. package/core/geoparquet-sql.js +327 -10
  45. package/core/odata-write-codec.d.ts.map +1 -1
  46. package/core/odata-write-codec.js +0 -1
  47. package/core/odata.d.ts +6 -0
  48. package/core/odata.d.ts.map +1 -1
  49. package/core/odata.js +6 -1
  50. package/core/ogc-processes.d.ts +182 -25
  51. package/core/ogc-processes.d.ts.map +1 -1
  52. package/core/ogc-processes.js +602 -30
  53. package/core/process-runner.d.ts +8 -1
  54. package/core/process-runner.d.ts.map +1 -1
  55. package/core/process-runner.js +1 -0
  56. package/core/protocol-transport.d.ts +2 -0
  57. package/core/protocol-transport.d.ts.map +1 -1
  58. package/core/stac.d.ts +32 -0
  59. package/core/stac.d.ts.map +1 -1
  60. package/core/stac.js +158 -23
  61. package/core/surfaces.d.ts.map +1 -1
  62. package/core/surfaces.js +273 -68
  63. package/core/types.d.ts +138 -11
  64. package/core/types.d.ts.map +1 -1
  65. package/core/wfs-axis-order.d.ts +18 -0
  66. package/core/wfs-axis-order.d.ts.map +1 -0
  67. package/core/wfs-axis-order.js +108 -0
  68. package/core/wfs-capabilities.d.ts +65 -24
  69. package/core/wfs-capabilities.d.ts.map +1 -1
  70. package/core/wfs-capabilities.js +237 -27
  71. package/core/wfs-filter.d.ts +26 -3
  72. package/core/wfs-filter.d.ts.map +1 -1
  73. package/core/wfs-filter.js +48 -53
  74. package/core/wfs-protocol-error.d.ts +12 -0
  75. package/core/wfs-protocol-error.d.ts.map +1 -0
  76. package/core/wfs-protocol-error.js +13 -0
  77. package/core/wfs.d.ts +53 -1
  78. package/core/wfs.d.ts.map +1 -1
  79. package/core/wfs.js +251 -29
  80. package/core/wms-feature-info.d.ts +92 -0
  81. package/core/wms-feature-info.d.ts.map +1 -0
  82. package/core/wms-feature-info.js +285 -0
  83. package/core/wms.d.ts +9 -0
  84. package/core/wms.d.ts.map +1 -1
  85. package/core/wms.js +17 -5
  86. package/esri-compat/event-bus.d.ts +20 -0
  87. package/esri-compat/event-bus.d.ts.map +1 -1
  88. package/esri-compat/feature-filter.d.ts +46 -1
  89. package/esri-compat/feature-filter.d.ts.map +1 -1
  90. package/esri-compat/feature-filter.js +49 -0
  91. package/esri-compat/geojson-layer.d.ts +4 -2
  92. package/esri-compat/geojson-layer.d.ts.map +1 -1
  93. package/esri-compat/geojson-layer.js +4 -2
  94. package/esri-compat/identity-manager.js +2 -2
  95. package/esri-compat/imagery-layer.d.ts +2 -1
  96. package/esri-compat/imagery-layer.d.ts.map +1 -1
  97. package/esri-compat/imagery-layer.js +2 -1
  98. package/esri-compat/layer-list.d.ts +8 -1
  99. package/esri-compat/layer-list.d.ts.map +1 -1
  100. package/esri-compat/layer-list.js +11 -4
  101. package/esri-compat/legend.d.ts.map +1 -1
  102. package/esri-compat/legend.js +1 -1
  103. package/esri-compat/locator.d.ts +297 -0
  104. package/esri-compat/locator.d.ts.map +1 -0
  105. package/esri-compat/locator.js +579 -0
  106. package/esri-compat/map-image-layer.d.ts.map +1 -1
  107. package/esri-compat/map-view.d.ts.map +1 -1
  108. package/esri-compat/map-view.js +1 -1
  109. package/esri-compat/scene-view.d.ts.map +1 -1
  110. package/esri-compat/time-slider.d.ts +29 -0
  111. package/esri-compat/time-slider.d.ts.map +1 -1
  112. package/esri-compat/time-slider.js +117 -0
  113. package/esri-compat/wfs-layer.d.ts +2 -1
  114. package/esri-compat/wfs-layer.d.ts.map +1 -1
  115. package/esri-compat/wfs-layer.js +2 -1
  116. package/esri-compat/widget-host.d.ts +42 -6
  117. package/esri-compat/widget-host.d.ts.map +1 -1
  118. package/esri-compat/widget-host.js +99 -10
  119. package/generated-app/projection.d.ts.map +1 -1
  120. package/generated-app/runtime.d.ts.map +1 -1
  121. package/interactions/declarative-contract.d.ts +149 -0
  122. package/interactions/declarative-contract.d.ts.map +1 -0
  123. package/interactions/declarative-contract.js +293 -0
  124. package/interactions/declarative.d.ts +198 -0
  125. package/interactions/declarative.d.ts.map +1 -0
  126. package/interactions/declarative.js +470 -0
  127. package/interactions/feature-state.d.ts +7 -0
  128. package/interactions/feature-state.d.ts.map +1 -1
  129. package/interactions/feature-state.js +10 -2
  130. package/map/data-to-map-bridge.d.ts +1 -1
  131. package/map/data-to-map-bridge.d.ts.map +1 -1
  132. package/map/data-to-map-bridge.js +1 -2
  133. package/map/honua-map.d.ts.map +1 -1
  134. package/map/honua-map.js +1 -1
  135. package/map/index.d.ts +2 -0
  136. package/map/index.d.ts.map +1 -1
  137. package/map/index.js +2 -0
  138. package/map/maplibre-target.js +1 -1
  139. package/map/realtime-reconciliation-adapter.d.ts +98 -0
  140. package/map/realtime-reconciliation-adapter.d.ts.map +1 -0
  141. package/map/realtime-reconciliation-adapter.js +84 -0
  142. package/map/temporal-playback.d.ts +25 -0
  143. package/map/temporal-playback.d.ts.map +1 -1
  144. package/map/temporal-playback.js +29 -1
  145. package/package.json +4 -3
  146. package/query-planner/canonical-filter.d.ts +30 -0
  147. package/query-planner/canonical-filter.d.ts.map +1 -0
  148. package/query-planner/canonical-filter.js +30 -0
  149. package/query-planner/columnar-plan.d.ts +63 -0
  150. package/query-planner/columnar-plan.d.ts.map +1 -0
  151. package/query-planner/columnar-plan.js +94 -0
  152. package/query-planner/diagnostics.d.ts +3 -3
  153. package/query-planner/diagnostics.d.ts.map +1 -1
  154. package/query-planner/diagnostics.js +17 -4
  155. package/query-planner/duckdb.d.ts.map +1 -1
  156. package/query-planner/duckdb.js +16 -2
  157. package/query-planner/execution-context.d.ts.map +1 -1
  158. package/query-planner/execution-context.js +3 -1
  159. package/query-planner/executor.d.ts.map +1 -1
  160. package/query-planner/executor.js +7 -1
  161. package/query-planner/geoservices.d.ts.map +1 -1
  162. package/query-planner/geoservices.js +24 -5
  163. package/query-planner/grpc.d.ts.map +1 -1
  164. package/query-planner/grpc.js +29 -5
  165. package/query-planner/index.d.ts +20 -5
  166. package/query-planner/index.d.ts.map +1 -1
  167. package/query-planner/index.js +16 -3
  168. package/query-planner/ir.d.ts +6 -1
  169. package/query-planner/ir.d.ts.map +1 -1
  170. package/query-planner/ir.js +63 -1
  171. package/query-planner/odata-protocol-module.d.ts +54 -0
  172. package/query-planner/odata-protocol-module.d.ts.map +1 -0
  173. package/query-planner/odata-protocol-module.js +199 -0
  174. package/query-planner/odata-v1.d.ts +23 -0
  175. package/query-planner/odata-v1.d.ts.map +1 -0
  176. package/query-planner/odata-v1.js +202 -0
  177. package/query-planner/odata.d.ts +0 -3
  178. package/query-planner/odata.d.ts.map +1 -1
  179. package/query-planner/odata.js +0 -143
  180. package/query-planner/ogc-features.d.ts.map +1 -1
  181. package/query-planner/ogc-features.js +23 -1
  182. package/query-planner/planner.d.ts +2 -2
  183. package/query-planner/planner.d.ts.map +1 -1
  184. package/query-planner/planner.js +146 -27
  185. package/query-planner/representation.d.ts +59 -0
  186. package/query-planner/representation.d.ts.map +1 -0
  187. package/query-planner/representation.js +140 -0
  188. package/query-planner/types.d.ts +153 -3
  189. package/query-planner/types.d.ts.map +1 -1
  190. package/query-planner/wfs-protocol-module.d.ts +57 -0
  191. package/query-planner/wfs-protocol-module.d.ts.map +1 -0
  192. package/query-planner/wfs-protocol-module.js +731 -0
  193. package/query-planner/wfs-v1.d.ts +41 -0
  194. package/query-planner/wfs-v1.d.ts.map +1 -0
  195. package/query-planner/wfs-v1.js +366 -0
  196. package/query-planner/wfs.d.ts +1 -3
  197. package/query-planner/wfs.d.ts.map +1 -1
  198. package/query-planner/wfs.js +1 -70
  199. package/react/honua-map.d.ts +3 -1
  200. package/react/honua-map.d.ts.map +1 -1
  201. package/react/honua-map.js +11 -1
  202. package/react/hooks.d.ts +1 -1
  203. package/react/hooks.js +1 -1
  204. package/react/selection.d.ts.map +1 -1
  205. package/react/selection.js +0 -0
  206. package/react/use-mounted-source.d.ts +1 -1
  207. package/react/use-mounted-source.js +1 -1
  208. package/realtime/checkpoint-store.d.ts +206 -0
  209. package/realtime/checkpoint-store.d.ts.map +1 -0
  210. package/realtime/checkpoint-store.js +504 -0
  211. package/realtime/contract.d.ts +142 -0
  212. package/realtime/contract.d.ts.map +1 -0
  213. package/realtime/contract.js +154 -0
  214. package/realtime/exploration.d.ts +16 -0
  215. package/realtime/exploration.d.ts.map +1 -0
  216. package/realtime/exploration.js +32 -0
  217. package/realtime/honua-server.d.ts +131 -0
  218. package/realtime/honua-server.d.ts.map +1 -0
  219. package/realtime/honua-server.js +302 -0
  220. package/realtime/index.d.ts +39 -0
  221. package/realtime/index.d.ts.map +1 -0
  222. package/realtime/index.js +26 -0
  223. package/realtime/odata-delta.d.ts +114 -0
  224. package/realtime/odata-delta.d.ts.map +1 -0
  225. package/realtime/odata-delta.js +483 -0
  226. package/realtime/projections.d.ts +30 -0
  227. package/realtime/projections.d.ts.map +1 -0
  228. package/realtime/projections.js +51 -0
  229. package/realtime/reconciliation.d.ts +245 -0
  230. package/realtime/reconciliation.d.ts.map +1 -0
  231. package/realtime/reconciliation.js +377 -0
  232. package/realtime/reducer.d.ts +14 -0
  233. package/realtime/reducer.d.ts.map +1 -0
  234. package/realtime/reducer.js +351 -0
  235. package/realtime/resumable-transport.d.ts +111 -0
  236. package/realtime/resumable-transport.d.ts.map +1 -0
  237. package/realtime/resumable-transport.js +406 -0
  238. package/realtime/resumable.d.ts +104 -0
  239. package/realtime/resumable.d.ts.map +1 -0
  240. package/realtime/resumable.js +632 -0
  241. package/realtime/sse.d.ts +23 -0
  242. package/realtime/sse.d.ts.map +1 -0
  243. package/realtime/sse.js +153 -0
  244. package/realtime/store.d.ts +18 -0
  245. package/realtime/store.d.ts.map +1 -0
  246. package/realtime/store.js +63 -0
  247. package/realtime/types.d.ts +190 -0
  248. package/realtime/types.d.ts.map +1 -0
  249. package/realtime/types.js +10 -0
  250. package/realtime/websocket.d.ts +60 -0
  251. package/realtime/websocket.d.ts.map +1 -0
  252. package/realtime/websocket.js +157 -0
  253. package/realtime/wire.d.ts +28 -0
  254. package/realtime/wire.d.ts.map +1 -0
  255. package/realtime/wire.js +73 -0
  256. package/runtime/index.d.ts +6 -2
  257. package/runtime/index.d.ts.map +1 -1
  258. package/runtime/index.js +3 -1
  259. package/runtime/load-package.d.ts +24 -0
  260. package/runtime/load-package.d.ts.map +1 -1
  261. package/runtime/load-package.js +45 -1
  262. package/runtime/maplibre-renderer.d.ts +11 -0
  263. package/runtime/maplibre-renderer.d.ts.map +1 -1
  264. package/runtime/maplibre-renderer.js +32 -7
  265. package/runtime/offline-region-protocol.d.ts +73 -0
  266. package/runtime/offline-region-protocol.d.ts.map +1 -0
  267. package/runtime/offline-region-protocol.js +63 -0
  268. package/runtime/offline-region-style.d.ts +78 -0
  269. package/runtime/offline-region-style.d.ts.map +1 -0
  270. package/runtime/offline-region-style.js +147 -0
  271. package/runtime/pmtiles-protocol.d.ts +7 -8
  272. package/runtime/pmtiles-protocol.d.ts.map +1 -1
  273. package/runtime/pmtiles-protocol.js +19 -66
  274. package/runtime/protocol-registry.d.ts +55 -0
  275. package/runtime/protocol-registry.d.ts.map +1 -0
  276. package/runtime/protocol-registry.js +103 -0
  277. package/runtime/runtime.d.ts +2 -0
  278. package/runtime/runtime.d.ts.map +1 -1
  279. package/runtime/runtime.js +6 -1
  280. package/runtime/style-compose.d.ts.map +1 -1
  281. package/runtime/style-compose.js +78 -9
  282. package/studio/index.d.ts +24 -7
  283. package/studio/index.d.ts.map +1 -1
  284. package/studio/index.js +21 -7
  285. package/studio/lifecycle-client.d.ts +164 -0
  286. package/studio/lifecycle-client.d.ts.map +1 -0
  287. package/studio/lifecycle-client.js +299 -0
  288. package/studio/lifecycle-errors.d.ts +91 -0
  289. package/studio/lifecycle-errors.d.ts.map +1 -0
  290. package/studio/lifecycle-errors.js +77 -0
  291. package/studio/lifecycle-types.d.ts +321 -0
  292. package/studio/lifecycle-types.d.ts.map +1 -0
  293. package/studio/lifecycle-types.js +22 -0
  294. package/webmap/convert-label.js +0 -1
  295. package/webmap/convert-symbol.d.ts.map +1 -1
@@ -0,0 +1,202 @@
1
+ import { compileQueryFilterToOData } from "../contract/query-filter.js";
2
+ import { buildOdataSpatialFilter, rewriteWhereToOdataFilter } from "../core/odata.js";
3
+ import { canonicalFilterParts, refuseCanonicalFilter } from "./canonical-filter.js";
4
+ import { HonuaQueryPlanningError } from "./types.js";
5
+ /** Compile canonical query IR to a deterministic OData v4 entity-set request. */
6
+ export function compileOdataQuery(source, query) {
7
+ if (source.protocol !== "odata") {
8
+ throw new HonuaQueryPlanningError("unsupported-compiler", `odata-v4-query-v1 does not compile protocol "${source.protocol}"`);
9
+ }
10
+ if (!source.entitySet) {
11
+ throw new HonuaQueryPlanningError("invalid-query", `Source "${source.id}" requires locator.entitySet for OData planning`);
12
+ }
13
+ if (query.aggregation) {
14
+ throw new HonuaQueryPlanningError("unsupported-query", "Canonical OData aggregation is not portable; use the typed $apply escape hatch");
15
+ }
16
+ if (query.outSr !== undefined) {
17
+ throw new HonuaQueryPlanningError("unsupported-query", "OData v4 has no portable output-CRS query option; omit outSr or use the typed OData escape hatch");
18
+ }
19
+ const ctx = {
20
+ protocol: source.protocol,
21
+ sourceId: source.id,
22
+ ...(source.geometryProperty !== undefined ? { geometryProperty: source.geometryProperty } : {}),
23
+ };
24
+ const parts = canonicalFilterParts(query, ctx);
25
+ if (parts.protocolTime) {
26
+ refuseCanonicalFilter("Query.temporalFilter without a field", "OData v4", "the protocol has no time parameter; name the temporal field so the predicate stays exact");
27
+ }
28
+ const filterParts = [];
29
+ try {
30
+ if (query.where) {
31
+ assertSupportedWhere(query.where.expression);
32
+ const rewritten = rewriteWhereToOdataFilter(query.where.expression);
33
+ if (rewritten)
34
+ filterParts.push(rewritten);
35
+ }
36
+ if (parts.expression) {
37
+ filterParts.push(compileQueryFilterToOData(parts.expression, ctx, (node) => {
38
+ if (!source.geometryProperty) {
39
+ throw new Error("descriptor schema does not identify the OData geometry column");
40
+ }
41
+ if (node.operator !== "intersects" && node.operator !== "bbox-intersects") {
42
+ throw new Error(`OData v4 has no standard ${node.operator} geo function`);
43
+ }
44
+ return buildOdataSpatialFilter({
45
+ geometry: node.geometry.geometry,
46
+ geometryType: node.geometry.geometryType,
47
+ spatialRel: "esriSpatialRelIntersects",
48
+ }, { geometryColumn: source.geometryProperty });
49
+ }));
50
+ }
51
+ if (query.spatialFilter) {
52
+ if (!source.geometryProperty) {
53
+ throw new Error("descriptor schema does not identify the OData geometry column");
54
+ }
55
+ filterParts.push(buildOdataSpatialFilter({
56
+ geometry: query.spatialFilter.geometry,
57
+ geometryType: query.spatialFilter.geometryType,
58
+ ...(query.spatialFilter.spatialRel ? { spatialRel: query.spatialFilter.spatialRel } : {}),
59
+ }, { geometryColumn: source.geometryProperty }));
60
+ }
61
+ }
62
+ catch (error) {
63
+ throw new HonuaQueryPlanningError("unsupported-query", `OData query cannot preserve the requested predicate: ${error instanceof Error ? error.message : String(error)}`);
64
+ }
65
+ let projection;
66
+ if (query.outFields && query.outFields.length > 0) {
67
+ projection = splitProjection(query.outFields, query.returnGeometry === false ? source.geometryProperty : undefined);
68
+ if (query.returnGeometry !== false &&
69
+ source.geometryProperty &&
70
+ !projection.select.includes(source.geometryProperty)) {
71
+ projection = { ...projection, select: [...projection.select, source.geometryProperty] };
72
+ }
73
+ }
74
+ else if (query.returnGeometry === false) {
75
+ throw new HonuaQueryPlanningError("unsupported-query", "Metadata-free OData planning requires explicit outFields to prove returnGeometry=false on the wire");
76
+ }
77
+ return {
78
+ compiler: "odata-v4-query-v1",
79
+ entitySet: source.entitySet,
80
+ ...(filterParts.length > 0 ? { filter: filterParts.join(" and ") } : {}),
81
+ ...(projection && projection.select.length > 0 ? { select: projection.select } : {}),
82
+ ...(projection && projection.expand.length > 0 ? { expand: projection.expand } : {}),
83
+ ...(query.orderBy && query.orderBy.length > 0
84
+ ? { orderBy: query.orderBy.map((sort) => `${sort.field}${sort.direction === "desc" ? " desc" : ""}`) }
85
+ : {}),
86
+ ...(query.pagination?.offset !== undefined ? { skip: query.pagination.offset } : {}),
87
+ ...(query.pagination?.limit !== undefined ? { top: query.pagination.limit } : {}),
88
+ };
89
+ }
90
+ /**
91
+ * The deterministic compiler hook installed on the first-party OData
92
+ * ProtocolModule. Planner dispatch and module consumers call this exact
93
+ * object, while runtime authority remains outside the compiler.
94
+ */
95
+ export const odataProtocolQueryCompiler = Object.freeze({
96
+ kind: "odata",
97
+ compile(input) {
98
+ return bindOdataProtocolQueryOperation(compileOdataQuery(input.source, input.query), input.operation);
99
+ },
100
+ });
101
+ /** Bind a legacy wire request to the exact operation authorized to execute it. */
102
+ export function bindOdataProtocolQueryOperation(compiled, operation) {
103
+ let top = compiled.top;
104
+ if (operation === "queryAll" && top !== undefined) {
105
+ if (!Number.isSafeInteger(top) || top < 0 || top >= Number.MAX_SAFE_INTEGER) {
106
+ throw new HonuaQueryPlanningError("invalid-query", "OData queryAll pagination.limit must leave room for one lookahead row");
107
+ }
108
+ top += 1;
109
+ }
110
+ return Object.freeze({
111
+ compiler: "odata-v4-protocol-query-v1",
112
+ operation,
113
+ entitySet: compiled.entitySet,
114
+ ...(compiled.filter !== undefined ? { filter: compiled.filter } : {}),
115
+ ...(compiled.select !== undefined ? { select: compiled.select } : {}),
116
+ ...(compiled.expand !== undefined ? { expand: compiled.expand } : {}),
117
+ ...(compiled.orderBy !== undefined ? { orderBy: compiled.orderBy } : {}),
118
+ ...(compiled.skip !== undefined ? { skip: compiled.skip } : {}),
119
+ ...(top !== undefined ? { top } : {}),
120
+ });
121
+ }
122
+ function assertSupportedWhere(where) {
123
+ const code = outsideQuotedStrings(where);
124
+ if (code === undefined)
125
+ throw new Error("unterminated OData string literal");
126
+ const unsupported = [
127
+ { expression: /\bLIKE\b/i, name: "LIKE" },
128
+ { expression: /\bBETWEEN\b/i, name: "BETWEEN" },
129
+ { expression: /==/, name: "==" },
130
+ { expression: /!=/, name: "!=" },
131
+ { expression: /;/, name: ";" },
132
+ ];
133
+ for (const candidate of unsupported) {
134
+ if (candidate.expression.test(code)) {
135
+ throw new Error(`operator ${candidate.name} is not translated by the OData compiler`);
136
+ }
137
+ }
138
+ }
139
+ /** Return only non-literal spans, or undefined for an unterminated literal. */
140
+ function outsideQuotedStrings(input) {
141
+ let output = "";
142
+ let quoted = false;
143
+ for (let index = 0; index < input.length; index += 1) {
144
+ const character = input[index];
145
+ if (character !== "'") {
146
+ if (!quoted)
147
+ output += character;
148
+ continue;
149
+ }
150
+ if (quoted && input[index + 1] === "'") {
151
+ index += 1;
152
+ continue;
153
+ }
154
+ quoted = !quoted;
155
+ }
156
+ return quoted ? undefined : output;
157
+ }
158
+ function splitProjection(fields, excludedGeometry) {
159
+ const root = { select: [], children: new Map() };
160
+ for (const field of fields) {
161
+ if (excludedGeometry && field === excludedGeometry)
162
+ continue;
163
+ const segments = field.split(".").filter(Boolean);
164
+ if (segments.length === 0)
165
+ continue;
166
+ let cursor = root;
167
+ for (let index = 0; index < segments.length - 1; index += 1) {
168
+ const segment = segments[index];
169
+ if (!segment)
170
+ continue;
171
+ let child = cursor.children.get(segment);
172
+ if (!child) {
173
+ child = { select: [], children: new Map() };
174
+ cursor.children.set(segment, child);
175
+ }
176
+ cursor = child;
177
+ }
178
+ const leaf = segments.at(-1);
179
+ if (leaf)
180
+ cursor.select.push(leaf);
181
+ }
182
+ const serialize = (node) => {
183
+ const parts = [];
184
+ if (node.select.length > 0)
185
+ parts.push(`$select=${node.select.join(",")}`);
186
+ if (node.children.size > 0) {
187
+ const children = [...node.children.entries()].map(([name, child]) => {
188
+ const inner = serialize(child);
189
+ return inner ? `${name}(${inner})` : name;
190
+ });
191
+ parts.push(`$expand=${children.join(",")}`);
192
+ }
193
+ return parts.join(";");
194
+ };
195
+ return {
196
+ select: root.select,
197
+ expand: [...root.children.entries()].map(([name, child]) => {
198
+ const inner = serialize(child);
199
+ return inner ? `${name}(${inner})` : name;
200
+ }),
201
+ };
202
+ }
@@ -2,9 +2,6 @@ import type { ExecutableCrsBinding, SourceSchemaV2 } from "../contract/schema.js
2
2
  import { type SemanticCompilationResult } from "./semantic-compiler.js";
3
3
  import { type SemanticCompilerFieldMapping } from "./semantic-literals.js";
4
4
  import type { SemanticQuery, SourceSpatiality } from "./semantic-types.js";
5
- import type { CanonicalQuery, OdataCompiledQueryV1, QueryIrSourceIdentity } from "./types.js";
6
- /** Compile canonical query IR to a deterministic OData v4 entity-set request. */
7
- export declare function compileOdataQuery(source: QueryIrSourceIdentity, query: CanonicalQuery): OdataCompiledQueryV1;
8
5
  export type SemanticOdataSpatialFunction = "geo.intersects" | "geo.distance";
9
6
  /** Static, credential-free OData endpoint evidence used by the semantic compiler. */
10
7
  export interface SemanticOdataSourceIdentity {
@@ -1 +1 @@
1
- {"version":3,"file":"odata.d.ts","sourceRoot":"","sources":["../../../src/query-planner/odata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,oBAAoB,EAOpB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAEL,KAAK,yBAAyB,EAO/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,4BAA4B,EAWlC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAe,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACxF,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAG9F,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,cAAc,GAAG,oBAAoB,CAoF5G;AAmFD,MAAM,MAAM,4BAA4B,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAE7E,qFAAqF;AACrF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,yBAAyB,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CAC9E;AAED,MAAM,WAAW,2BAA2B,CAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,SAAS,gBAAgB,GAAG,gBAAgB;IAEvD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;CAC9C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,oBAAoB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;CACvB;AAED,6DAA6D;AAC7D,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,CAAC,EAAE,2BAA2B,CAAC;IACtD,QAAQ,CAAC,aAAa,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAChE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AA0BD,+EAA+E;AAC/E,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,SAAS,gBAAgB,EACrF,OAAO,EAAE,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC,GACzD,yBAAyB,CAAC,4BAA4B,CAAC,CA4CzD"}
1
+ {"version":3,"file":"odata.d.ts","sourceRoot":"","sources":["../../../src/query-planner/odata.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,oBAAoB,EAOpB,cAAc,EACf,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEL,KAAK,yBAAyB,EAO/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,KAAK,4BAA4B,EAWlC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAe,aAAa,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGxF,MAAM,MAAM,4BAA4B,GAAG,gBAAgB,GAAG,cAAc,CAAC;AAE7E,qFAAqF;AACrF,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,6EAA6E;IAC7E,QAAQ,CAAC,yBAAyB,CAAC,EAAE,SAAS,4BAA4B,EAAE,CAAC;CAC9E;AAED,MAAM,WAAW,2BAA2B,CAC1C,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,SAAS,gBAAgB,GAAG,gBAAgB;IAEvD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC;IAC7D,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAC;CAC9C;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,WAAW,EAAE,WAAW,GAAG,UAAU,CAAC;IAC/C,QAAQ,CAAC,GAAG,EAAE,oBAAoB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC;CACvB;AAED,6DAA6D;AAC7D,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,CAAC,EAAE,2BAA2B,CAAC;IACtD,QAAQ,CAAC,aAAa,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAChE,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AA0BD,+EAA+E;AAC/E,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,SAAS,gBAAgB,EACrF,OAAO,EAAE,2BAA2B,CAAC,OAAO,EAAE,WAAW,CAAC,GACzD,yBAAyB,CAAC,4BAA4B,CAAC,CA4CzD"}
@@ -1,151 +1,8 @@
1
1
  import { validateExecutableCrsBinding } from "../contract/schema.js";
2
- import { buildOdataSpatialFilter, rewriteWhereToOdataFilter } from "../core/odata.js";
3
2
  import { hashSemanticQuery } from "./semantic-canonical.js";
4
3
  import { prepareSemanticCompilerQuery, runSemanticCompiler, sameCrsDefinition, sameExecutableCrs, semanticSchemaField, semanticUnsupported, } from "./semantic-compiler.js";
5
4
  import { exactDecimalText, finiteDecimalNumber, odataPropertyPath, quotedSemanticString, recordSemanticFieldMapping, semanticRequestFingerprint, sortSemanticFieldMappings, verifiedSemanticNativeText, verifiedSemanticSourceText, verifiedSemanticSourceVersion, } from "./semantic-literals.js";
6
5
  import { HonuaQueryPlanningError } from "./types.js";
7
- /** Compile canonical query IR to a deterministic OData v4 entity-set request. */
8
- export function compileOdataQuery(source, query) {
9
- if (source.protocol !== "odata") {
10
- throw new HonuaQueryPlanningError("unsupported-compiler", `odata-v4-query-v1 does not compile protocol "${source.protocol}"`);
11
- }
12
- if (!source.entitySet) {
13
- throw new HonuaQueryPlanningError("invalid-query", `Source "${source.id}" requires locator.entitySet for OData planning`);
14
- }
15
- if (query.aggregation) {
16
- throw new HonuaQueryPlanningError("unsupported-query", "Canonical OData aggregation is not portable; use the typed $apply escape hatch");
17
- }
18
- if (query.outSr !== undefined) {
19
- throw new HonuaQueryPlanningError("unsupported-query", "OData v4 has no portable output-CRS query option; omit outSr or use the typed OData escape hatch");
20
- }
21
- const filterParts = [];
22
- try {
23
- if (query.where) {
24
- assertSupportedWhere(query.where.expression);
25
- const rewritten = rewriteWhereToOdataFilter(query.where.expression);
26
- if (rewritten)
27
- filterParts.push(rewritten);
28
- }
29
- if (query.spatialFilter) {
30
- if (!source.geometryProperty) {
31
- throw new Error("descriptor schema does not identify the OData geometry column");
32
- }
33
- filterParts.push(buildOdataSpatialFilter({
34
- geometry: query.spatialFilter.geometry,
35
- geometryType: query.spatialFilter.geometryType,
36
- ...(query.spatialFilter.spatialRel ? { spatialRel: query.spatialFilter.spatialRel } : {}),
37
- }, { geometryColumn: source.geometryProperty }));
38
- }
39
- }
40
- catch (error) {
41
- throw new HonuaQueryPlanningError("unsupported-query", `OData query cannot preserve the requested predicate: ${error instanceof Error ? error.message : String(error)}`);
42
- }
43
- let projection;
44
- if (query.outFields && query.outFields.length > 0) {
45
- projection = splitProjection(query.outFields, query.returnGeometry === false ? source.geometryProperty : undefined);
46
- if (query.returnGeometry !== false &&
47
- source.geometryProperty &&
48
- !projection.select.includes(source.geometryProperty)) {
49
- projection = { ...projection, select: [...projection.select, source.geometryProperty] };
50
- }
51
- }
52
- else if (query.returnGeometry === false) {
53
- throw new HonuaQueryPlanningError("unsupported-query", "Metadata-free OData planning requires explicit outFields to prove returnGeometry=false on the wire");
54
- }
55
- return {
56
- compiler: "odata-v4-query-v1",
57
- entitySet: source.entitySet,
58
- ...(filterParts.length > 0 ? { filter: filterParts.join(" and ") } : {}),
59
- ...(projection && projection.select.length > 0 ? { select: projection.select } : {}),
60
- ...(projection && projection.expand.length > 0 ? { expand: projection.expand } : {}),
61
- ...(query.orderBy && query.orderBy.length > 0
62
- ? { orderBy: query.orderBy.map((sort) => `${sort.field}${sort.direction === "desc" ? " desc" : ""}`) }
63
- : {}),
64
- ...(query.pagination?.offset !== undefined ? { skip: query.pagination.offset } : {}),
65
- ...(query.pagination?.limit !== undefined ? { top: query.pagination.limit } : {}),
66
- };
67
- }
68
- function assertSupportedWhere(where) {
69
- const code = outsideQuotedStrings(where);
70
- if (code === undefined)
71
- throw new Error("unterminated OData string literal");
72
- const unsupported = [
73
- { expression: /\bLIKE\b/i, name: "LIKE" },
74
- { expression: /\bBETWEEN\b/i, name: "BETWEEN" },
75
- { expression: /==/, name: "==" },
76
- { expression: /!=/, name: "!=" },
77
- { expression: /;/, name: ";" },
78
- ];
79
- for (const candidate of unsupported) {
80
- if (candidate.expression.test(code)) {
81
- throw new Error(`operator ${candidate.name} is not translated by the OData compiler`);
82
- }
83
- }
84
- }
85
- /** Return only non-literal spans, or undefined for an unterminated literal. */
86
- function outsideQuotedStrings(input) {
87
- let output = "";
88
- let quoted = false;
89
- for (let index = 0; index < input.length; index += 1) {
90
- const character = input[index];
91
- if (character !== "'") {
92
- if (!quoted)
93
- output += character;
94
- continue;
95
- }
96
- if (quoted && input[index + 1] === "'") {
97
- index += 1;
98
- continue;
99
- }
100
- quoted = !quoted;
101
- }
102
- return quoted ? undefined : output;
103
- }
104
- function splitProjection(fields, excludedGeometry) {
105
- const root = { select: [], children: new Map() };
106
- for (const field of fields) {
107
- if (excludedGeometry && field === excludedGeometry)
108
- continue;
109
- const segments = field.split(".").filter(Boolean);
110
- if (segments.length === 0)
111
- continue;
112
- let cursor = root;
113
- for (let index = 0; index < segments.length - 1; index += 1) {
114
- const segment = segments[index];
115
- if (!segment)
116
- continue;
117
- let child = cursor.children.get(segment);
118
- if (!child) {
119
- child = { select: [], children: new Map() };
120
- cursor.children.set(segment, child);
121
- }
122
- cursor = child;
123
- }
124
- const leaf = segments.at(-1);
125
- if (leaf)
126
- cursor.select.push(leaf);
127
- }
128
- const serialize = (node) => {
129
- const parts = [];
130
- if (node.select.length > 0)
131
- parts.push(`$select=${node.select.join(",")}`);
132
- if (node.children.size > 0) {
133
- const children = [...node.children.entries()].map(([name, child]) => {
134
- const inner = serialize(child);
135
- return inner ? `${name}(${inner})` : name;
136
- });
137
- parts.push(`$expand=${children.join(",")}`);
138
- }
139
- return parts.join(";");
140
- };
141
- return {
142
- select: root.select,
143
- expand: [...root.children.entries()].map(([name, child]) => {
144
- const inner = serialize(child);
145
- return inner ? `${name}(${inner})` : name;
146
- }),
147
- };
148
- }
149
6
  const ODATA_COMPARISON_OPERATOR = {
150
7
  eq: "eq",
151
8
  ne: "ne",
@@ -1 +1 @@
1
- {"version":3,"file":"ogc-features.d.ts","sourceRoot":"","sources":["../../../src/query-planner/ogc-features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAA2B,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAqB3G,OAAO,EAEL,KAAK,yBAAyB,EAI/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAGV,aAAa,EACb,gBAAgB,EAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGvG,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,WAAW,uCAAuC;IACtD,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,2EAA2E;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,oCAAoC;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,oCAAoC,CACnD,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,SAAS,gBAAgB,GAAG,gBAAgB;IAEvD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IACpE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,oCAAoC,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,uCAAuC,CAAC;IAC9D,yFAAyF;IACzF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,kBAAkB,CAAC;IACtD,2GAA2G;IAC3G,QAAQ,CAAC,eAAe,CAAC,EAAE,oBAAoB,CAAC;CACjD;AAED,yEAAyE;AACzE,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,QAAQ,EAAE,oCAAoC,CAAC;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,qBAAqB,EAAE,UAAU,MAAM,EAAE,CAAC;IACnD,QAAQ,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAuED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,cAAc,GACpB,6BAA6B,CAuC/B;AAED,wFAAwF;AACxF,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,WAAW,SAAS,gBAAgB,EAC9F,OAAO,EAAE,oCAAoC,CAAC,OAAO,EAAE,WAAW,CAAC,GAClE,yBAAyB,CAAC,qCAAqC,CAAC,CAiDlE"}
1
+ {"version":3,"file":"ogc-features.d.ts","sourceRoot":"","sources":["../../../src/query-planner/ogc-features.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,oBAAoB,EAA2B,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAuB3G,OAAO,EAEL,KAAK,yBAAyB,EAI/B,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAGV,aAAa,EACb,gBAAgB,EAEjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,cAAc,EAAE,6BAA6B,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAGvG,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,WAAW,CAAC;AAE3D,6EAA6E;AAC7E,MAAM,WAAW,uCAAuC;IACtD,+EAA+E;IAC/E,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,iFAAiF;IACjF,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,2EAA2E;IAC3E,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjD;AAED,MAAM,WAAW,oCAAoC;IACnD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;CACxC;AAED,MAAM,WAAW,oCAAoC,CACnD,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,WAAW,SAAS,gBAAgB,GAAG,gBAAgB;IAEvD,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,CAAC,CAAC;IACpE,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,oCAAoC,CAAC;IACtD,QAAQ,CAAC,WAAW,EAAE,uCAAuC,CAAC;IAC9D,yFAAyF;IACzF,QAAQ,CAAC,uBAAuB,CAAC,EAAE,kBAAkB,CAAC;IACtD,2GAA2G;IAC3G,QAAQ,CAAC,eAAe,CAAC,EAAE,oBAAoB,CAAC;CACjD;AAED,yEAAyE;AACzE,MAAM,WAAW,qCAAqC;IACpD,QAAQ,CAAC,QAAQ,EAAE,oCAAoC,CAAC;IACxD,QAAQ,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC;IACtC,QAAQ,CAAC,iBAAiB,EAAE,cAAc,CAAC,aAAa,CAAC,CAAC;IAC1D,QAAQ,CAAC,gBAAgB,EAAE,UAAU,MAAM,EAAE,CAAC;IAC9C,QAAQ,CAAC,qBAAqB,EAAE,UAAU,MAAM,EAAE,CAAC;IACnD,QAAQ,CAAC,kBAAkB,EAAE,UAAU,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IACvC,gFAAgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,CAAC,EAAE,kBAAkB,CAAC;IACzC,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACpC;AAuED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,cAAc,GACpB,6BAA6B,CA4D/B;AAED,wFAAwF;AACxF,wBAAgB,kCAAkC,CAAC,OAAO,EAAE,WAAW,SAAS,gBAAgB,EAC9F,OAAO,EAAE,oCAAoC,CAAC,OAAO,EAAE,WAAW,CAAC,GAClE,yBAAyB,CAAC,qCAAqC,CAAC,CAiDlE"}
@@ -1,3 +1,6 @@
1
+ import { compileQueryFilterToCql2Text, compileTemporalFilterToOgcDatetime, } from "../contract/query-filter.js";
2
+ import { geometryToWkt as esriGeometryToWkt } from "../core/odata.js";
3
+ import { canonicalFilterParts } from "./canonical-filter.js";
1
4
  import { canonicalStringify, toJsonValue } from "./canonical.js";
2
5
  import { bboxInDefinitionOrder, compiledRequestFingerprint, compilerEvidenceFingerprint, compilerField, cql2FieldName, cql2Identifier, cql2StringLiteral, geometryInDefinitionOrder, geometryToWkt, hasConformanceClass, normalizeConformanceUris, normalizeIdentifierUris, ogcAxisPlan, ogcCrsUri, ogcNumber, sharedFilterCrs, } from "./ogc-compiler.js";
3
6
  import { hashSemanticQuery } from "./semantic-canonical.js";
@@ -66,10 +69,29 @@ export function compileOgcApiFeaturesQuery(source, query) {
66
69
  if (query.returnGeometry === false) {
67
70
  throw new HonuaQueryPlanningError("unsupported-query", "OGC API Features /items has no portable geometry-suppression parameter; omit returnGeometry or select another protocol");
68
71
  }
72
+ const ctx = {
73
+ protocol: source.protocol,
74
+ sourceId: source.id,
75
+ geometryProperty: source.geometryProperty ?? "geometry",
76
+ };
77
+ const parts = canonicalFilterParts(query, ctx);
78
+ const typedFilter = parts.expression
79
+ ? compileQueryFilterToCql2Text(parts.expression, ctx, esriGeometryToWkt)
80
+ : undefined;
81
+ const filterParts = [
82
+ ...(query.where ? [query.where.expression] : []),
83
+ ...(typedFilter !== undefined ? [typedFilter] : []),
84
+ ];
85
+ const filter = filterParts.length === 0
86
+ ? undefined
87
+ : filterParts.length === 1
88
+ ? filterParts[0]
89
+ : filterParts.map((part) => `(${part})`).join(" AND ");
69
90
  return {
70
91
  compiler: "ogc-api-features-query-v1",
71
92
  collectionId: source.collectionId,
72
- ...(query.where ? { filter: query.where.expression, filterLang: "cql2-text" } : {}),
93
+ ...(filter !== undefined ? { filter, filterLang: "cql2-text" } : {}),
94
+ ...(parts.protocolTime ? { datetime: compileTemporalFilterToOgcDatetime(parts.protocolTime, ctx) } : {}),
73
95
  ...(query.outFields && query.outFields.length > 0 ? { properties: query.outFields } : {}),
74
96
  ...(query.orderBy && query.orderBy.length > 0
75
97
  ? { sortby: query.orderBy.map((sort) => `${sort.direction === "desc" ? "-" : ""}${sort.field}`).join(",") }
@@ -6,9 +6,9 @@ export declare function hashQueryPlan(plan: QueryExecutionPlan): `sha256:${strin
6
6
  export declare function hashQueryPlanV1(plan: QueryExecutionPlanV1): `sha256:${string}` | undefined;
7
7
  /** Internal executor boundary: validate once and continue with an immutable detached snapshot. */
8
8
  export declare function validateQueryPlanSnapshot(plan: QueryExecutionPlan): QueryExecutionPlan;
9
- /** Canonical persistence boundary for accepted v1/v2 query plans. */
9
+ /** Canonical persistence boundary; validated legacy protocol artifacts are upgraded before serialization. */
10
10
  export declare function serializeQueryPlan(plan: QueryExecutionPlan): string;
11
- /** Parse a persisted plan without retaining invalid JSON or credential-bearing v1 locators. */
11
+ /** Parse a persisted plan, upgrading validated legacy protocol artifacts without retaining unsafe input. */
12
12
  export declare function parseQueryPlan(serialized: string): QueryExecutionPlan;
13
13
  /** Stable cache identity derived only after the plan passes the persistence guard. */
14
14
  export declare function queryPlanCacheKey(plan: QueryExecutionPlan): string;
@@ -1 +1 @@
1
- {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../src/query-planner/planner.ts"],"names":[],"mappings":"AAwBA,OAAO,EAIL,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EAUxB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAM1B,MAAM,YAAY,CAAC;AAGpB,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC;AACjG,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC;AAqMvF,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,UAAU,MAAM,EAAE,CAE1E;AAED,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,IAAI,EAAE,oBAAoB,GAAG,UAAU,MAAM,EAAE,GAAG,SAAS,CAkB1F;AAED,kGAAkG;AAClG,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAItF;AAED,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAInE;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAWrE;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAIlE;AAED,qFAAqF;AACrF,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,oBAAoB,EAChC,aAAa,EAAE,OAAO,GACrB,oBAAoB,CAiCtB"}
1
+ {"version":3,"file":"planner.d.ts","sourceRoot":"","sources":["../../../src/query-planner/planner.ts"],"names":[],"mappings":"AAyBA,OAAO,EAIL,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EASxB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAO1B,MAAM,YAAY,CAAC;AAGpB,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC;AACjG,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,oBAAoB,CAAC;AAwNvF,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,UAAU,MAAM,EAAE,CAE1E;AAED,qGAAqG;AACrG,wBAAgB,eAAe,CAAC,IAAI,EAAE,oBAAoB,GAAG,UAAU,MAAM,EAAE,GAAG,SAAS,CAkB1F;AAED,kGAAkG;AAClG,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAItF;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAInE;AAED,4GAA4G;AAC5G,wBAAgB,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,kBAAkB,CAWrE;AAED,sFAAsF;AACtF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAIlE;AAED,qFAAqF;AACrF,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,oBAAoB,EAChC,aAAa,EAAE,OAAO,GACrB,oBAAoB,CAkCtB"}