@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.
- package/contract/discovery.d.ts +34 -0
- package/contract/discovery.d.ts.map +1 -1
- package/contract/index.d.ts +7 -5
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +3 -2
- package/contract/pmtiles.d.ts +10 -1
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +10 -2
- package/contract/protocol-module.d.ts +84 -9
- package/contract/protocol-module.d.ts.map +1 -1
- package/contract/query-filter-fes.d.ts +18 -0
- package/contract/query-filter-fes.d.ts.map +1 -0
- package/contract/query-filter-fes.js +122 -0
- package/contract/query-filter.d.ts +300 -0
- package/contract/query-filter.d.ts.map +1 -0
- package/contract/query-filter.js +883 -0
- package/contract/schema.d.ts +12 -0
- package/contract/schema.d.ts.map +1 -1
- package/contract/schema.js +34 -0
- package/contract/source-capability-support.d.ts.map +1 -1
- package/contract/source-capability-support.js +15 -3
- package/contract/source.d.ts +45 -25
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +719 -479
- package/contract/types.d.ts +87 -18
- package/contract/types.d.ts.map +1 -1
- package/contract/widget-source.d.ts.map +1 -1
- package/core/client.d.ts +45 -21
- package/core/client.d.ts.map +1 -1
- package/core/client.js +224 -46
- package/core/error-classifications.d.ts +6 -0
- package/core/error-classifications.d.ts.map +1 -1
- package/core/error-classifications.js +6 -0
- package/core/error-code-registry.d.ts +6 -0
- package/core/error-code-registry.d.ts.map +1 -1
- package/core/error-code-registry.js +6 -0
- package/core/error-envelope.js +2 -0
- package/core/errors.d.ts +1 -1
- package/core/errors.js +1 -1
- package/core/geoparquet-sql.d.ts +68 -4
- package/core/geoparquet-sql.d.ts.map +1 -1
- package/core/geoparquet-sql.js +325 -8
- package/core/odata-write-codec.d.ts.map +1 -1
- package/core/odata-write-codec.js +0 -1
- package/core/odata.d.ts +6 -0
- package/core/odata.d.ts.map +1 -1
- package/core/odata.js +6 -1
- package/core/ogc-processes.d.ts +182 -25
- package/core/ogc-processes.d.ts.map +1 -1
- package/core/ogc-processes.js +602 -30
- package/core/process-runner.d.ts +8 -1
- package/core/process-runner.d.ts.map +1 -1
- package/core/process-runner.js +1 -0
- package/core/protocol-transport.d.ts +2 -0
- package/core/protocol-transport.d.ts.map +1 -1
- package/core/stac.d.ts +31 -0
- package/core/stac.d.ts.map +1 -1
- package/core/stac.js +136 -19
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +273 -68
- package/core/types.d.ts +123 -9
- package/core/types.d.ts.map +1 -1
- package/core/wfs-axis-order.d.ts +18 -0
- package/core/wfs-axis-order.d.ts.map +1 -0
- package/core/wfs-axis-order.js +108 -0
- package/core/wfs-capabilities.d.ts +65 -24
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +237 -27
- package/core/wfs-filter.d.ts +26 -3
- package/core/wfs-filter.d.ts.map +1 -1
- package/core/wfs-filter.js +48 -53
- package/core/wfs-protocol-error.d.ts +12 -0
- package/core/wfs-protocol-error.d.ts.map +1 -0
- package/core/wfs-protocol-error.js +13 -0
- package/core/wfs.d.ts +53 -1
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +251 -29
- package/core/wms-feature-info.d.ts +92 -0
- package/core/wms-feature-info.d.ts.map +1 -0
- package/core/wms-feature-info.js +285 -0
- package/core/wms.d.ts +9 -0
- package/core/wms.d.ts.map +1 -1
- package/core/wms.js +17 -5
- package/esri-compat/event-bus.d.ts +20 -0
- package/esri-compat/event-bus.d.ts.map +1 -1
- package/esri-compat/feature-filter.d.ts +46 -1
- package/esri-compat/feature-filter.d.ts.map +1 -1
- package/esri-compat/feature-filter.js +49 -0
- package/esri-compat/geojson-layer.d.ts +4 -2
- package/esri-compat/geojson-layer.d.ts.map +1 -1
- package/esri-compat/geojson-layer.js +4 -2
- package/esri-compat/identity-manager.js +2 -2
- package/esri-compat/imagery-layer.d.ts +2 -1
- package/esri-compat/imagery-layer.d.ts.map +1 -1
- package/esri-compat/imagery-layer.js +2 -1
- package/esri-compat/layer-list.d.ts +8 -1
- package/esri-compat/layer-list.d.ts.map +1 -1
- package/esri-compat/layer-list.js +11 -4
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +1 -1
- package/esri-compat/locator.d.ts +297 -0
- package/esri-compat/locator.d.ts.map +1 -0
- package/esri-compat/locator.js +579 -0
- package/esri-compat/map-image-layer.d.ts.map +1 -1
- package/esri-compat/map-view.d.ts.map +1 -1
- package/esri-compat/map-view.js +1 -1
- package/esri-compat/scene-view.d.ts.map +1 -1
- package/esri-compat/time-slider.d.ts +29 -0
- package/esri-compat/time-slider.d.ts.map +1 -1
- package/esri-compat/time-slider.js +117 -0
- package/esri-compat/wfs-layer.d.ts +2 -1
- package/esri-compat/wfs-layer.d.ts.map +1 -1
- package/esri-compat/wfs-layer.js +2 -1
- package/esri-compat/widget-host.d.ts +42 -6
- package/esri-compat/widget-host.d.ts.map +1 -1
- package/esri-compat/widget-host.js +99 -10
- package/generated-app/projection.d.ts.map +1 -1
- package/generated-app/runtime.d.ts.map +1 -1
- package/map/data-to-map-bridge.d.ts +1 -1
- package/map/data-to-map-bridge.d.ts.map +1 -1
- package/map/data-to-map-bridge.js +1 -2
- package/map/honua-map.d.ts.map +1 -1
- package/map/honua-map.js +1 -1
- package/map/index.d.ts +2 -0
- package/map/index.d.ts.map +1 -1
- package/map/index.js +2 -0
- package/map/realtime-reconciliation-adapter.d.ts +98 -0
- package/map/realtime-reconciliation-adapter.d.ts.map +1 -0
- package/map/realtime-reconciliation-adapter.js +84 -0
- package/map/temporal-playback.d.ts +25 -0
- package/map/temporal-playback.d.ts.map +1 -1
- package/map/temporal-playback.js +29 -1
- package/package.json +4 -3
- package/query-planner/canonical-filter.d.ts +30 -0
- package/query-planner/canonical-filter.d.ts.map +1 -0
- package/query-planner/canonical-filter.js +30 -0
- package/query-planner/columnar-plan.d.ts +63 -0
- package/query-planner/columnar-plan.d.ts.map +1 -0
- package/query-planner/columnar-plan.js +94 -0
- package/query-planner/diagnostics.d.ts +3 -3
- package/query-planner/diagnostics.d.ts.map +1 -1
- package/query-planner/diagnostics.js +17 -4
- package/query-planner/duckdb.d.ts.map +1 -1
- package/query-planner/duckdb.js +16 -2
- package/query-planner/execution-context.d.ts.map +1 -1
- package/query-planner/execution-context.js +3 -1
- package/query-planner/executor.d.ts.map +1 -1
- package/query-planner/executor.js +7 -1
- package/query-planner/geoservices.d.ts.map +1 -1
- package/query-planner/geoservices.js +24 -5
- package/query-planner/grpc.d.ts.map +1 -1
- package/query-planner/grpc.js +29 -5
- package/query-planner/index.d.ts +20 -5
- package/query-planner/index.d.ts.map +1 -1
- package/query-planner/index.js +16 -3
- package/query-planner/ir.d.ts +6 -1
- package/query-planner/ir.d.ts.map +1 -1
- package/query-planner/ir.js +63 -1
- package/query-planner/odata-protocol-module.d.ts +54 -0
- package/query-planner/odata-protocol-module.d.ts.map +1 -0
- package/query-planner/odata-protocol-module.js +199 -0
- package/query-planner/odata-v1.d.ts +23 -0
- package/query-planner/odata-v1.d.ts.map +1 -0
- package/query-planner/odata-v1.js +202 -0
- package/query-planner/odata.d.ts +0 -3
- package/query-planner/odata.d.ts.map +1 -1
- package/query-planner/odata.js +0 -143
- package/query-planner/ogc-features.d.ts.map +1 -1
- package/query-planner/ogc-features.js +23 -1
- package/query-planner/planner.d.ts +2 -2
- package/query-planner/planner.d.ts.map +1 -1
- package/query-planner/planner.js +146 -27
- package/query-planner/representation.d.ts +59 -0
- package/query-planner/representation.d.ts.map +1 -0
- package/query-planner/representation.js +140 -0
- package/query-planner/types.d.ts +153 -3
- package/query-planner/types.d.ts.map +1 -1
- package/query-planner/wfs-protocol-module.d.ts +57 -0
- package/query-planner/wfs-protocol-module.d.ts.map +1 -0
- package/query-planner/wfs-protocol-module.js +731 -0
- package/query-planner/wfs-v1.d.ts +41 -0
- package/query-planner/wfs-v1.d.ts.map +1 -0
- package/query-planner/wfs-v1.js +366 -0
- package/query-planner/wfs.d.ts +1 -3
- package/query-planner/wfs.d.ts.map +1 -1
- package/query-planner/wfs.js +1 -70
- package/react/honua-map.d.ts +3 -1
- package/react/honua-map.d.ts.map +1 -1
- package/react/honua-map.js +11 -1
- package/react/hooks.d.ts +1 -1
- package/react/hooks.js +1 -1
- package/react/selection.d.ts.map +1 -1
- package/react/selection.js +0 -0
- package/react/use-mounted-source.d.ts +1 -1
- package/react/use-mounted-source.js +1 -1
- package/realtime/checkpoint-store.d.ts +206 -0
- package/realtime/checkpoint-store.d.ts.map +1 -0
- package/realtime/checkpoint-store.js +504 -0
- package/realtime/contract.d.ts +142 -0
- package/realtime/contract.d.ts.map +1 -0
- package/realtime/contract.js +154 -0
- package/realtime/exploration.d.ts +16 -0
- package/realtime/exploration.d.ts.map +1 -0
- package/realtime/exploration.js +32 -0
- package/realtime/honua-server.d.ts +131 -0
- package/realtime/honua-server.d.ts.map +1 -0
- package/realtime/honua-server.js +302 -0
- package/realtime/index.d.ts +39 -0
- package/realtime/index.d.ts.map +1 -0
- package/realtime/index.js +26 -0
- package/realtime/odata-delta.d.ts +114 -0
- package/realtime/odata-delta.d.ts.map +1 -0
- package/realtime/odata-delta.js +483 -0
- package/realtime/projections.d.ts +30 -0
- package/realtime/projections.d.ts.map +1 -0
- package/realtime/projections.js +51 -0
- package/realtime/reconciliation.d.ts +245 -0
- package/realtime/reconciliation.d.ts.map +1 -0
- package/realtime/reconciliation.js +377 -0
- package/realtime/reducer.d.ts +14 -0
- package/realtime/reducer.d.ts.map +1 -0
- package/realtime/reducer.js +351 -0
- package/realtime/resumable-transport.d.ts +111 -0
- package/realtime/resumable-transport.d.ts.map +1 -0
- package/realtime/resumable-transport.js +406 -0
- package/realtime/resumable.d.ts +104 -0
- package/realtime/resumable.d.ts.map +1 -0
- package/realtime/resumable.js +632 -0
- package/realtime/sse.d.ts +23 -0
- package/realtime/sse.d.ts.map +1 -0
- package/realtime/sse.js +147 -0
- package/realtime/store.d.ts +18 -0
- package/realtime/store.d.ts.map +1 -0
- package/realtime/store.js +63 -0
- package/realtime/types.d.ts +190 -0
- package/realtime/types.d.ts.map +1 -0
- package/realtime/types.js +10 -0
- package/realtime/websocket.d.ts +60 -0
- package/realtime/websocket.d.ts.map +1 -0
- package/realtime/websocket.js +157 -0
- package/realtime/wire.d.ts +28 -0
- package/realtime/wire.d.ts.map +1 -0
- package/realtime/wire.js +73 -0
- package/runtime/index.d.ts +6 -2
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +3 -1
- package/runtime/load-package.d.ts +24 -0
- package/runtime/load-package.d.ts.map +1 -1
- package/runtime/load-package.js +45 -1
- package/runtime/maplibre-renderer.d.ts +11 -0
- package/runtime/maplibre-renderer.d.ts.map +1 -1
- package/runtime/maplibre-renderer.js +32 -7
- package/runtime/offline-region-protocol.d.ts +73 -0
- package/runtime/offline-region-protocol.d.ts.map +1 -0
- package/runtime/offline-region-protocol.js +63 -0
- package/runtime/offline-region-style.d.ts +78 -0
- package/runtime/offline-region-style.d.ts.map +1 -0
- package/runtime/offline-region-style.js +147 -0
- package/runtime/pmtiles-protocol.d.ts +7 -8
- package/runtime/pmtiles-protocol.d.ts.map +1 -1
- package/runtime/pmtiles-protocol.js +19 -66
- package/runtime/protocol-registry.d.ts +55 -0
- package/runtime/protocol-registry.d.ts.map +1 -0
- package/runtime/protocol-registry.js +103 -0
- package/runtime/runtime.d.ts +2 -0
- package/runtime/runtime.d.ts.map +1 -1
- package/runtime/runtime.js +6 -1
- package/studio/index.d.ts +24 -7
- package/studio/index.d.ts.map +1 -1
- package/studio/index.js +21 -7
- package/studio/lifecycle-client.d.ts +164 -0
- package/studio/lifecycle-client.d.ts.map +1 -0
- package/studio/lifecycle-client.js +299 -0
- package/studio/lifecycle-errors.d.ts +91 -0
- package/studio/lifecycle-errors.d.ts.map +1 -0
- package/studio/lifecycle-errors.js +77 -0
- package/studio/lifecycle-types.d.ts +321 -0
- package/studio/lifecycle-types.d.ts.map +1 -0
- package/studio/lifecycle-types.js +22 -0
- package/webmap/convert-label.js +0 -1
- package/webmap/convert-symbol.d.ts.map +1 -1
package/query-planner/index.js
CHANGED
|
@@ -11,13 +11,19 @@
|
|
|
11
11
|
* @packageDocumentation
|
|
12
12
|
*/
|
|
13
13
|
export { canonicalStringify, sha256, toJsonValue } from "./canonical.js";
|
|
14
|
+
export { columnarBatchIdentityFromPlan } from "./columnar-plan.js";
|
|
15
|
+
export { COLUMNAR_REPRESENTATION_ENCODINGS, COLUMNAR_REPRESENTATION_MIN_BYTES, COLUMNAR_REPRESENTATION_MIN_ROWS, createQueryPlanRepresentationDecision, isColumnarRepresentationEncoding, } from "./representation.js";
|
|
14
16
|
export { compileDuckDbQuery, compileDuckDbQueryV2, compileSemanticDuckDbQuery } from "./duckdb.js";
|
|
15
17
|
export { executeQueryPlan } from "./executor.js";
|
|
16
18
|
export { compileGeoServicesQuery, compileSemanticGeoServicesQuery } from "./geoservices.js";
|
|
17
19
|
export { compileGrpcQuery, compileSemanticGrpcQuery } from "./grpc.js";
|
|
18
20
|
export { compileOgcApiFeaturesQuery, compileSemanticOgcApiFeaturesQuery } from "./ogc-features.js";
|
|
19
|
-
export {
|
|
20
|
-
export {
|
|
21
|
+
export { odataProtocolModule } from "./odata-protocol-module.js";
|
|
22
|
+
export { compileOdataQuery } from "./odata-v1.js";
|
|
23
|
+
export { compileSemanticOdataQuery } from "./odata.js";
|
|
24
|
+
export { HonuaWfsProtocolError, wfsProtocolModule } from "./wfs-protocol-module.js";
|
|
25
|
+
export { compileWfsQuery } from "./wfs-v1.js";
|
|
26
|
+
export { compileSemanticWfsQuery } from "./wfs.js";
|
|
21
27
|
export { canonicalizeQuery, createGeoParquetQueryIr, createQueryIr, hashQueryIr, queryFromCanonical, } from "./ir.js";
|
|
22
28
|
export { explainQuery, hashQueryPlan, migrateGeoParquetQueryPlanV1, parseQueryPlan, queryPlanCacheKey, serializeQueryPlan, } from "./planner.js";
|
|
23
29
|
export { QUERY_RESOURCE_HANDLE_KIND, QUERY_RESOURCE_HANDLE_VERSION, createGeoParquetResourceHandle, createGeoParquetResourceRegistry, hashGeoParquetResourceHandle, parseGeoParquetResourceHandle, resolveGeoParquetResource, } from "./resource.js";
|
|
@@ -25,6 +31,13 @@ export { SEMANTIC_QUERY_CANONICAL_KIND, SEMANTIC_QUERY_CANONICAL_VERSION, SEMANT
|
|
|
25
31
|
export { legacyWhereToNativeFilter } from "./semantic-compat.js";
|
|
26
32
|
export { semanticFilterFromCql2Json, semanticFilterToCql2Json } from "./cql2-json.js";
|
|
27
33
|
export { MAX_SEMANTIC_QUERY_BYTES, MAX_SEMANTIC_QUERY_COLLECTION_ITEMS, MAX_SEMANTIC_QUERY_DEPTH, MAX_SEMANTIC_QUERY_NODES, MAX_SEMANTIC_QUERY_TEXT_BYTES, createSemanticQueryBuilder, defineSemanticQuery, defineSpatialNode, parseSemanticQuery, temporalLiteral, } from "./semantic.js";
|
|
28
|
-
export { COLUMNAR_WORKER_CANCEL_KIND, COLUMNAR_WORKER_ERROR_KIND, COLUMNAR_WORKER_PROGRESS_KIND, COLUMNAR_WORKER_PROTOCOL_VERSION, COLUMNAR_WORKER_REQUEST_KIND, COLUMNAR_WORKER_RESULT_KIND, ColumnarBatchLease, GEOARROW_SPEC_VERSION, HONUA_GEOARROW_LAYOUT_VERSION, HonuaGeoArrowError, HonuaColumnarWorkerError, createColumnarBatch, createColumnarWorkerSession, createGeoArrowBatch, decodeGeoArrowBatch, fromApacheArrowRecordBatch, inspectGeoArrowBatch, inspectColumnarBatch, leaseColumnarBatch, loadApacheArrow, startColumnarWorkerHost, toApacheArrowRecordBatch, } from "../columnar/index.js";
|
|
34
|
+
export { COLUMNAR_WORKER_CANCEL_KIND, COLUMNAR_WORKER_ERROR_KIND, COLUMNAR_WORKER_PROGRESS_KIND, COLUMNAR_WORKER_PROTOCOL_VERSION, COLUMNAR_WORKER_REQUEST_KIND, COLUMNAR_WORKER_RESULT_KIND, ColumnarBatchLease, DEFAULT_GEOARROW_AGGREGATE_MAX_GROUPS, DEFAULT_GEOARROW_AGGREGATE_YIELD_ROWS, GEOARROW_AGGREGATE_ABORT_CHECK_ROWS, GEOARROW_AGGREGATE_MAX_GRID_CELL_INDEX, GEOARROW_SPEC_VERSION, HONUA_GEOARROW_AGGREGATE_LAYOUT_VERSION, HONUA_GEOARROW_LAYOUT_VERSION, HonuaGeoArrowError, HonuaColumnarWorkerError, createColumnarBatch, createColumnarWorkerSession, createGeoArrowAggregateOperation, createGeoArrowBatch, createGeoArrowReprojectOperation, readGeoArrowAggregateBatch, deserializeGeoArrowBatch, decodeGeoArrowBatch, fromApacheArrowRecordBatch, inspectGeoArrowBatch, inspectColumnarBatch, leaseColumnarBatch, loadApacheArrow, startColumnarWorkerHost, serializeGeoArrowBatch, toApacheArrowRecordBatch, } from "../columnar/index.js";
|
|
35
|
+
// Bounded conversion between a columnar batch and an object `Result` (#942).
|
|
36
|
+
// It shipped documented as part of this entrypoint but was never re-exported
|
|
37
|
+
// here, so it was unreachable through a subpath; the telemetry seam below
|
|
38
|
+
// observes it, which requires a caller able to reach it.
|
|
39
|
+
export { DEFAULT_COLUMNAR_RESULT_MAX_FEATURES, columnarBatchToResult, columnarBatchToResultPages, resultToColumnarBatch, } from "../columnar/index.js";
|
|
40
|
+
export { COLUMNAR_PATCH_ABORT_CHECK_ROWS, COLUMNAR_PATCH_KIND, COLUMNAR_PATCH_VERSION, DEFAULT_COLUMNAR_PATCH_MAX_CAPACITY_UTILIZATION, DEFAULT_COLUMNAR_PATCH_MAX_OPERATIONS, DEFAULT_COLUMNAR_PATCH_MAX_TOMBSTONE_OVERLAY_BYTES, DEFAULT_COLUMNAR_PATCH_MAX_TOMBSTONE_RATIO, DEFAULT_COLUMNAR_PATCH_MAX_VERTEX_GROWTH_RATIO, HONUA_COLUMNAR_PATCH_LAYOUT_VERSION, HonuaColumnarPatchError, applyColumnarPatch, columnarPatchLiveMask, createColumnarPatch, createColumnarPatchOperation, createPatchableGeoArrowBatch, decodePatchedGeoArrowBatch, inspectColumnarPatchState, } from "../columnar/index.js";
|
|
41
|
+
export { COLUMNAR_BATCH_CACHE_CONFORMANCE_CASES, DEFAULT_COLUMNAR_BATCH_CACHE_MAX_AGE_MS, DEFAULT_COLUMNAR_BATCH_CACHE_MAX_RECORDS, DEFAULT_COLUMNAR_BATCH_CACHE_QUOTA_BYTES, GEOARROW_ENVELOPE_MIGRATIONS, HONUA_COLUMNAR_BATCH_CACHE_CONFORMANCE_KIND, HONUA_COLUMNAR_BATCH_CACHE_CONFORMANCE_VERSION, HONUA_COLUMNAR_BATCH_CACHE_FORMAT, HONUA_GEOARROW_ENVELOPE_KIND, HONUA_GEOARROW_ENVELOPE_VERSION, MAX_COLUMNAR_BATCH_CACHE_MAX_AGE_MS, MAX_COLUMNAR_BATCH_CACHE_MAX_RECORDS, MAX_COLUMNAR_BATCH_CACHE_QUOTA_BYTES, columnarAuthorizationScopeDigest, columnarBatchCacheFixtureBatch, columnarBatchCacheFixtureIdentity, columnarBatchCacheKey, columnarBatchCacheLegacyEntry, columnarBatchCacheOrderingDigest, createColumnarBatchCache, createIndexedDbColumnarBatchCacheStorage, createMemoryColumnarBatchCacheStorage, planColumnarBatchCacheAdmission, planGeoArrowEnvelopeMigration, readableGeoArrowEnvelopeVersions, runColumnarBatchCacheConformance, } from "../columnar/index.js";
|
|
29
42
|
export { COLUMNAR_BATCH_KIND, COLUMNAR_BATCH_VERSION, COLUMNAR_TRANSFER_KIND, DEFAULT_COLUMNAR_BATCH_MAX_BACKING_BYTES, DEFAULT_COLUMNAR_BATCH_MAX_BUFFER_VIEWS, DEFAULT_COLUMNAR_BATCH_MAX_METADATA_ENTRIES, DEFAULT_COLUMNAR_BATCH_MAX_ROWS, DEFAULT_COLUMNAR_BATCH_MAX_SCHEMA_NODES, DEFAULT_COLUMNAR_BATCH_MAX_STRING_BYTES, HonuaColumnarTransferError, } from "../columnar/index.js";
|
|
30
43
|
export { HonuaQueryPlanExecutionError, HonuaQueryPlanningError, MAX_LOCAL_MATERIALIZATION_ROWS, QUERY_IR_KIND, QUERY_IR_VERSION, QUERY_PLAN_KIND, QUERY_PLAN_DIAGNOSTICS_VERSION, QUERY_PLANNER_VERSION, QUERY_PLAN_VERSION, QUERY_IR_V2_VERSION, QUERY_PLAN_V2_VERSION, } from "./types.js";
|
package/query-planner/ir.d.ts
CHANGED
|
@@ -13,7 +13,12 @@ export declare function createGeoParquetQueryIr<T>(options: ExplainGeoParquetQue
|
|
|
13
13
|
export declare function hashQueryIr(ir: QueryIrV1 | QueryIrV2): `sha256:${string}`;
|
|
14
14
|
export declare function canonicalizeQuery<T>(query?: Readonly<Query<T>>): CanonicalQuery;
|
|
15
15
|
export declare function queryFromCanonical<T>(query: CanonicalQuery, signal?: AbortSignal): Query<T>;
|
|
16
|
-
export declare function queryIrSourceIdentity(descriptor: SourceDescriptor, context?: Pick<ExplainQueryOptions, "authorizationScope" | "schemaVersion" | "sourceVersion">): QueryIrSourceIdentity;
|
|
16
|
+
export declare function queryIrSourceIdentity(descriptor: SourceDescriptor, context?: Pick<ExplainQueryOptions, "authorizationScope" | "schemaVersion" | "sourceVersion" | "sourceAuthorityFingerprint">): QueryIrSourceIdentity;
|
|
17
|
+
/**
|
|
18
|
+
* Derive a stable WFS authority binding without retaining endpoint
|
|
19
|
+
* credentials, signed-query values, fragments, or authorization material.
|
|
20
|
+
*/
|
|
21
|
+
export declare function queryIrAuthorityFingerprint(rawUrl: string, authorizationScope?: readonly string[]): `sha256:${string}`;
|
|
17
22
|
/** Rebuild the exact credential-free source identity used by a GeoParquet v2 plan. */
|
|
18
23
|
export declare function queryIrSourceIdentityV2(descriptor: SourceDescriptor, resourceValue: unknown, context?: GeoParquetV2IdentityContext): QueryIrSourceIdentityV2;
|
|
19
24
|
export declare function deepFreeze<T>(value: T): T;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../../src/query-planner/ir.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGrF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EAMrC,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAIpB,qGAAqG;AACrG,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,gCAAgC,EAAE,CAAC;CACxE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,CAgB3E;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,GAAG,SAAS,CAgB/F;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,MAAM,EAAE,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"ir.d.ts","sourceRoot":"","sources":["../../../src/query-planner/ir.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmB,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGrF,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,6BAA6B,EAClC,KAAK,mBAAmB,EACxB,KAAK,gCAAgC,EAMrC,KAAK,qBAAqB,EAC1B,KAAK,uBAAuB,EAC5B,KAAK,SAAS,EACd,KAAK,SAAS,EACf,MAAM,YAAY,CAAC;AAIpB,qGAAqG;AACrG,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChD,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,eAAe,CAAC,EAAE,SAAS,gCAAgC,EAAE,CAAC;CACxE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,SAAS,CAgB3E;AAED,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,OAAO,EAAE,6BAA6B,CAAC,CAAC,CAAC,GAAG,SAAS,CAgB/F;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,SAAS,GAAG,SAAS,GAAG,UAAU,MAAM,EAAE,CAEzE;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,cAAc,CA0C/E;AAED,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAsB3F;AAED,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,gBAAgB,EAC5B,OAAO,GAAE,IAAI,CACX,mBAAmB,EACnB,oBAAoB,GAAG,eAAe,GAAG,eAAe,GAAG,4BAA4B,CACnF,GACL,qBAAqB,CA+CvB;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,kBAAkB,GAAE,SAAS,MAAM,EAAO,GACzC,UAAU,MAAM,EAAE,CAepB;AAED,sFAAsF;AACtF,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,gBAAgB,EAC5B,aAAa,EAAE,OAAO,EACtB,OAAO,GAAE,2BAAgC,GACxC,uBAAuB,CAwDzB;AAiRD,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAMzC"}
|
package/query-planner/ir.js
CHANGED
|
@@ -45,6 +45,11 @@ export function canonicalizeQuery(query) {
|
|
|
45
45
|
assertSafeNativeExpression(query.where);
|
|
46
46
|
const canonical = {
|
|
47
47
|
...(query.where !== undefined ? { where: { kind: "source-native", expression: query.where } } : {}),
|
|
48
|
+
// The typed filter and temporal member are identity-bearing: they change
|
|
49
|
+
// which rows a plan returns, so they belong in the canonical bytes that
|
|
50
|
+
// `hashQueryIr` / `hashQueryPlan` fingerprint.
|
|
51
|
+
...(query.filter !== undefined ? { filter: query.filter } : {}),
|
|
52
|
+
...(query.temporalFilter !== undefined ? { temporalFilter: query.temporalFilter } : {}),
|
|
48
53
|
...(query.spatialFilter
|
|
49
54
|
? {
|
|
50
55
|
spatialFilter: {
|
|
@@ -81,6 +86,8 @@ export function canonicalizeQuery(query) {
|
|
|
81
86
|
export function queryFromCanonical(query, signal) {
|
|
82
87
|
return {
|
|
83
88
|
...(query.where ? { where: query.where.expression } : {}),
|
|
89
|
+
...(query.filter !== undefined ? { filter: query.filter } : {}),
|
|
90
|
+
...(query.temporalFilter !== undefined ? { temporalFilter: query.temporalFilter } : {}),
|
|
84
91
|
...(query.spatialFilter
|
|
85
92
|
? {
|
|
86
93
|
spatialFilter: {
|
|
@@ -104,14 +111,30 @@ export function queryIrSourceIdentity(descriptor, context = {}) {
|
|
|
104
111
|
if (authorizationScope.some((scope) => !isStableAuthorizationScope(scope))) {
|
|
105
112
|
throw new HonuaQueryPlanningError("invalid-query", "authorization scope identity is invalid");
|
|
106
113
|
}
|
|
107
|
-
|
|
114
|
+
// WFS names its geometry property per feature type; `locator.geometryName`
|
|
115
|
+
// carries either the caller's explicit pin or the value the adapter resolved
|
|
116
|
+
// from DescribeFeatureType, and outranks descriptor schema evidence.
|
|
117
|
+
const geometryProperty = (descriptor.protocol === "wfs" ? descriptor.locator.geometryName : undefined) ??
|
|
118
|
+
descriptor.schema?.fields?.find((field) => field.type === "esriFieldTypeGeometry")?.name;
|
|
108
119
|
const geoparquet = descriptor.protocol === "geoparquet" ? geoparquetIdentity(descriptor, geometryProperty) : undefined;
|
|
109
120
|
const schemaVersion = optionalPlanMetadata(context.schemaVersion, "schema version");
|
|
110
121
|
const sourceVersion = optionalPlanMetadata(context.sourceVersion, "source version");
|
|
122
|
+
const authorityFingerprint = descriptor.protocol === "wfs"
|
|
123
|
+
? context.sourceAuthorityFingerprint === null
|
|
124
|
+
? undefined
|
|
125
|
+
: (context.sourceAuthorityFingerprint ??
|
|
126
|
+
queryIrAuthorityFingerprint(descriptor.locator.url, authorizationScope))
|
|
127
|
+
: undefined;
|
|
128
|
+
if (context.sourceAuthorityFingerprint !== undefined &&
|
|
129
|
+
context.sourceAuthorityFingerprint !== null &&
|
|
130
|
+
!/^sha256:[0-9a-f]{64}$/.test(context.sourceAuthorityFingerprint)) {
|
|
131
|
+
throw new HonuaQueryPlanningError("invalid-query", "source authority fingerprint is invalid");
|
|
132
|
+
}
|
|
111
133
|
return deepFreeze({
|
|
112
134
|
id: descriptor.id,
|
|
113
135
|
protocol: descriptor.protocol,
|
|
114
136
|
endpoint: credentialFreeEndpoint(descriptor.locator.url),
|
|
137
|
+
...(authorityFingerprint ? { authorityFingerprint } : {}),
|
|
115
138
|
...(descriptor.locator.serviceId !== undefined ? { serviceId: descriptor.locator.serviceId } : {}),
|
|
116
139
|
...(descriptor.locator.layerId !== undefined ? { layerId: descriptor.locator.layerId } : {}),
|
|
117
140
|
...(descriptor.locator.collectionId !== undefined ? { collectionId: descriptor.locator.collectionId } : {}),
|
|
@@ -126,6 +149,22 @@ export function queryIrSourceIdentity(descriptor, context = {}) {
|
|
|
126
149
|
capabilities: [...descriptor.capabilities].sort(),
|
|
127
150
|
});
|
|
128
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Derive a stable WFS authority binding without retaining endpoint
|
|
154
|
+
* credentials, signed-query values, fragments, or authorization material.
|
|
155
|
+
*/
|
|
156
|
+
export function queryIrAuthorityFingerprint(rawUrl, authorizationScope = []) {
|
|
157
|
+
const scopes = [...new Set(authorizationScope)].sort();
|
|
158
|
+
if (scopes.some((scope) => !isStableAuthorizationScope(scope))) {
|
|
159
|
+
throw new HonuaQueryPlanningError("invalid-query", "authorization scope identity is invalid");
|
|
160
|
+
}
|
|
161
|
+
const authority = canonicalAuthorityMaterial(rawUrl);
|
|
162
|
+
return sha256(canonicalStringify(toJsonValue({
|
|
163
|
+
domain: "honua:wfs-authority:v1",
|
|
164
|
+
authority,
|
|
165
|
+
authorizationScope: scopes,
|
|
166
|
+
})));
|
|
167
|
+
}
|
|
129
168
|
/** Rebuild the exact credential-free source identity used by a GeoParquet v2 plan. */
|
|
130
169
|
export function queryIrSourceIdentityV2(descriptor, resourceValue, context = {}) {
|
|
131
170
|
if (descriptor.protocol !== "geoparquet") {
|
|
@@ -317,6 +356,29 @@ function asJsonObject(value, path) {
|
|
|
317
356
|
}
|
|
318
357
|
return json;
|
|
319
358
|
}
|
|
359
|
+
function canonicalAuthorityMaterial(rawUrl) {
|
|
360
|
+
if (typeof rawUrl !== "string" || rawUrl.length === 0) {
|
|
361
|
+
throw new HonuaQueryPlanningError("invalid-query", "source authority endpoint is invalid");
|
|
362
|
+
}
|
|
363
|
+
try {
|
|
364
|
+
const parsed = new URL(rawUrl);
|
|
365
|
+
parsed.hash = "";
|
|
366
|
+
const search = parsed.search;
|
|
367
|
+
parsed.search = "";
|
|
368
|
+
return `${parsed.toString().replace(/\/$/, "")}${search}`;
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
const withoutFragment = rawUrl.split("#", 1)[0] ?? rawUrl;
|
|
372
|
+
const queryIndex = withoutFragment.indexOf("?");
|
|
373
|
+
const path = queryIndex >= 0 ? withoutFragment.slice(0, queryIndex) : withoutFragment;
|
|
374
|
+
const search = queryIndex >= 0 ? withoutFragment.slice(queryIndex) : "";
|
|
375
|
+
const normalized = path === "/" ? "/" : path.replace(/\/$/, "");
|
|
376
|
+
if (normalized.length === 0 || hasSchemeAuthorityPrefix(rawUrl) || startsWithDoubleSlash(rawUrl)) {
|
|
377
|
+
throw new HonuaQueryPlanningError("invalid-query", "source authority endpoint is invalid");
|
|
378
|
+
}
|
|
379
|
+
return `${normalized}${search}`;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
320
382
|
function credentialFreeEndpoint(rawUrl) {
|
|
321
383
|
const invalidEndpoint = "[invalid-endpoint]";
|
|
322
384
|
try {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* First-party OData v4 protocol module.
|
|
3
|
+
*
|
|
4
|
+
* The module owns the same typed `HonuaOdataEntitySet` escape hatch exposed by
|
|
5
|
+
* `Source.protocol("odata")`, the deterministic planner compiler hook, and
|
|
6
|
+
* canonical query/queryAll wire execution. Runtime authority is the
|
|
7
|
+
* `HonuaClient` explicitly injected into {@link odataProtocolModule}; compiled
|
|
8
|
+
* artifacts carry no origin or credentials and cannot redirect a discovered
|
|
9
|
+
* handle to another entity set.
|
|
10
|
+
*
|
|
11
|
+
* @module
|
|
12
|
+
*/
|
|
13
|
+
import type { ProtocolModuleQueryBinding, ProtocolModuleQueryOperation, QueryCapableProtocolModule } from "../contract/protocol-module.js";
|
|
14
|
+
import type { Result, SourceDescriptor } from "../contract/types.js";
|
|
15
|
+
import type { HonuaClient } from "../core/client.js";
|
|
16
|
+
import { HonuaOdataEntitySet, type HonuaOdataPage, type HonuaOdataQueryParams } from "../core/odata.js";
|
|
17
|
+
import type { HonuaFieldInfo } from "../core/types.js";
|
|
18
|
+
import type { CanonicalQuery, OdataProtocolCompiledQueryV1, QueryIrSourceIdentity } from "./types.js";
|
|
19
|
+
/** Runtime-only OData execution context. None of these values enter a plan fingerprint. */
|
|
20
|
+
export interface OdataProtocolExecutionQuery {
|
|
21
|
+
readonly count: boolean;
|
|
22
|
+
readonly fields: ReadonlyArray<HonuaFieldInfo>;
|
|
23
|
+
readonly returnGeometry?: boolean;
|
|
24
|
+
readonly geometryColumn?: string;
|
|
25
|
+
readonly limit?: number;
|
|
26
|
+
}
|
|
27
|
+
/** Exact compiler/executor types carried by the OData protocol module. */
|
|
28
|
+
export interface OdataProtocolQueryBinding extends ProtocolModuleQueryBinding {
|
|
29
|
+
readonly source: QueryIrSourceIdentity;
|
|
30
|
+
readonly compileQuery: CanonicalQuery;
|
|
31
|
+
readonly compiled: OdataProtocolCompiledQueryV1;
|
|
32
|
+
readonly executeQuery: OdataProtocolExecutionQuery;
|
|
33
|
+
}
|
|
34
|
+
export type OdataProtocolModule = QueryCapableProtocolModule<"odata", HonuaOdataEntitySet, OdataProtocolQueryBinding>;
|
|
35
|
+
/**
|
|
36
|
+
* Project already-negotiated OData query params onto the credential-free
|
|
37
|
+
* deterministic artifact consumed by the module executor.
|
|
38
|
+
*
|
|
39
|
+
* `count` and `signal` are intentionally omitted: count is runtime response
|
|
40
|
+
* metadata policy, and cancellation can never participate in request identity.
|
|
41
|
+
*/
|
|
42
|
+
export declare function createOdataProtocolCompiledQuery(entitySet: string, operation: ProtocolModuleQueryOperation, params: HonuaOdataQueryParams): OdataProtocolCompiledQueryV1;
|
|
43
|
+
/**
|
|
44
|
+
* Construct the first-party query-capable OData protocol module.
|
|
45
|
+
*
|
|
46
|
+
* Discovery is synchronous and performs no I/O. `$metadata` remains lazy on
|
|
47
|
+
* the returned `HonuaOdataEntitySet`, exactly as it was before the migration.
|
|
48
|
+
* The client stays in this module instance's closure; there is no global
|
|
49
|
+
* protocol registry or ambient authority.
|
|
50
|
+
*/
|
|
51
|
+
export declare function odataProtocolModule(client: HonuaClient): OdataProtocolModule;
|
|
52
|
+
/** Internal shared result projection used by query execution and OData streaming. */
|
|
53
|
+
export declare function odataProtocolResultFromPage<T>(descriptor: SourceDescriptor, page: HonuaOdataPage<Record<string, unknown>>, fields: ReadonlyArray<HonuaFieldInfo>, returnGeometry: boolean | undefined, geometryColumn: string | undefined): Result<T>;
|
|
54
|
+
//# sourceMappingURL=odata-protocol-module.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"odata-protocol-module.d.ts","sourceRoot":"","sources":["../../../src/query-planner/odata-protocol-module.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAEV,0BAA0B,EAE1B,4BAA4B,EAC5B,0BAA0B,EAC3B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAA0B,MAAM,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7F,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,KAAK,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAExG,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AAE1E,OAAO,KAAK,EACV,cAAc,EAEd,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,2FAA2F;AAC3F,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAC/C,QAAQ,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,0EAA0E;AAC1E,MAAM,WAAW,yBAA0B,SAAQ,0BAA0B;IAC3E,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAC;IACvC,QAAQ,CAAC,YAAY,EAAE,cAAc,CAAC;IACtC,QAAQ,CAAC,QAAQ,EAAE,4BAA4B,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE,2BAA2B,CAAC;CACpD;AAED,MAAM,MAAM,mBAAmB,GAAG,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,EAAE,yBAAyB,CAAC,CAAC;AAEtH;;;;;;GAMG;AACH,wBAAgB,gCAAgC,CAC9C,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,4BAA4B,EACvC,MAAM,EAAE,qBAAqB,GAC5B,4BAA4B,CAY9B;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,mBAAmB,CAwE5E;AA2FD,qFAAqF;AACrF,wBAAgB,2BAA2B,CAAC,CAAC,EAC3C,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,EAC7C,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,EACrC,cAAc,EAAE,OAAO,GAAG,SAAS,EACnC,cAAc,EAAE,MAAM,GAAG,SAAS,GACjC,MAAM,CAAC,CAAC,CAAC,CAUX"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { PROTOCOL_DEFAULT_CAPABILITIES } from "../contract/types.js";
|
|
2
|
+
import { HonuaCapabilityNotSupportedError } from "../core/errors.js";
|
|
3
|
+
import { HonuaOdataEntitySet } from "../core/odata.js";
|
|
4
|
+
import { trimTrailingSlashes } from "../core/path-utils.js";
|
|
5
|
+
import { bindOdataProtocolQueryOperation, odataProtocolQueryCompiler } from "./odata-v1.js";
|
|
6
|
+
/**
|
|
7
|
+
* Project already-negotiated OData query params onto the credential-free
|
|
8
|
+
* deterministic artifact consumed by the module executor.
|
|
9
|
+
*
|
|
10
|
+
* `count` and `signal` are intentionally omitted: count is runtime response
|
|
11
|
+
* metadata policy, and cancellation can never participate in request identity.
|
|
12
|
+
*/
|
|
13
|
+
export function createOdataProtocolCompiledQuery(entitySet, operation, params) {
|
|
14
|
+
const request = Object.freeze({
|
|
15
|
+
compiler: "odata-v4-query-v1",
|
|
16
|
+
entitySet,
|
|
17
|
+
...(params.filter !== undefined ? { filter: params.filter } : {}),
|
|
18
|
+
...(params.select !== undefined ? { select: Object.freeze([...params.select]) } : {}),
|
|
19
|
+
...(params.expand !== undefined ? { expand: Object.freeze([...params.expand]) } : {}),
|
|
20
|
+
...(params.orderBy !== undefined ? { orderBy: Object.freeze([...params.orderBy]) } : {}),
|
|
21
|
+
...(params.skip !== undefined ? { skip: params.skip } : {}),
|
|
22
|
+
...(params.top !== undefined ? { top: params.top } : {}),
|
|
23
|
+
});
|
|
24
|
+
return bindOdataProtocolQueryOperation(request, operation);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Construct the first-party query-capable OData protocol module.
|
|
28
|
+
*
|
|
29
|
+
* Discovery is synchronous and performs no I/O. `$metadata` remains lazy on
|
|
30
|
+
* the returned `HonuaOdataEntitySet`, exactly as it was before the migration.
|
|
31
|
+
* The client stays in this module instance's closure; there is no global
|
|
32
|
+
* protocol registry or ambient authority.
|
|
33
|
+
*/
|
|
34
|
+
export function odataProtocolModule(client) {
|
|
35
|
+
return Object.freeze({
|
|
36
|
+
kind: "odata",
|
|
37
|
+
environments: Object.freeze(["browser", "node", "worker"]),
|
|
38
|
+
capabilities(descriptor) {
|
|
39
|
+
return descriptor.capabilities ?? PROTOCOL_DEFAULT_CAPABILITIES.odata;
|
|
40
|
+
},
|
|
41
|
+
discover(descriptor) {
|
|
42
|
+
const { entitySet, basePath } = requireOdataLocator(descriptor);
|
|
43
|
+
const adapter = new HonuaOdataEntitySet({ client, entitySet, basePath });
|
|
44
|
+
return Object.freeze({
|
|
45
|
+
descriptor,
|
|
46
|
+
capabilities: descriptor.capabilities ?? PROTOCOL_DEFAULT_CAPABILITIES.odata,
|
|
47
|
+
adapter,
|
|
48
|
+
diagnostics: Object.freeze([]),
|
|
49
|
+
dispose() {
|
|
50
|
+
// HonuaOdataEntitySet retains only settled/in-flight promises and
|
|
51
|
+
// opens no persistent handles. Disposal is deterministic and
|
|
52
|
+
// synchronous with nothing to release.
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
},
|
|
56
|
+
compile: odataProtocolQueryCompiler.compile,
|
|
57
|
+
async execute(handle, input) {
|
|
58
|
+
assertExecutableOdataArtifact(handle.adapter, input.compiled, input.operation);
|
|
59
|
+
const logicalLimit = input.operation === "queryAll"
|
|
60
|
+
? resolveOdataQueryAllLogicalLimit(input.compiled, input.query.limit)
|
|
61
|
+
: undefined;
|
|
62
|
+
const params = odataParamsFromCompiled(input.compiled, input.query.count, input.signal);
|
|
63
|
+
switch (input.operation) {
|
|
64
|
+
case "query": {
|
|
65
|
+
const page = await handle.adapter.query(params);
|
|
66
|
+
return odataProtocolResultFromPage(handle.descriptor, page, input.query.fields, input.query.returnGeometry, input.query.geometryColumn);
|
|
67
|
+
}
|
|
68
|
+
case "queryAll": {
|
|
69
|
+
const drained = await handle.adapter.queryAll(params);
|
|
70
|
+
const allFeatures = drained.rows.map((row) => odataRowToFeature(row, handle.descriptor, input.query.returnGeometry, input.query.geometryColumn));
|
|
71
|
+
const { features, exceededTransferLimit: collectedExceeded } = applyLimit(allFeatures, logicalLimit);
|
|
72
|
+
const countExceeded = typeof drained.totalCount === "number" &&
|
|
73
|
+
typeof logicalLimit === "number" &&
|
|
74
|
+
drained.totalCount > features.length;
|
|
75
|
+
return {
|
|
76
|
+
features,
|
|
77
|
+
exceededTransferLimit: collectedExceeded || countExceeded,
|
|
78
|
+
...(typeof drained.totalCount === "number"
|
|
79
|
+
? { totalCount: drained.totalCount }
|
|
80
|
+
: { totalCount: features.length }),
|
|
81
|
+
...(input.query.fields.length > 0 ? { fields: input.query.fields } : {}),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
case "queryAggregate":
|
|
85
|
+
throw new HonuaCapabilityNotSupportedError("queryAggregate", handle.descriptor.protocol, handle.descriptor.id);
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
function requireOdataLocator(descriptor) {
|
|
91
|
+
const { entitySet, url, layerId } = descriptor.locator;
|
|
92
|
+
let resolvedEntitySet;
|
|
93
|
+
if (typeof entitySet === "string" && entitySet !== "") {
|
|
94
|
+
resolvedEntitySet = entitySet;
|
|
95
|
+
}
|
|
96
|
+
else if (typeof layerId === "number" && Number.isFinite(layerId)) {
|
|
97
|
+
resolvedEntitySet = `Layers(${layerId})/Features`;
|
|
98
|
+
}
|
|
99
|
+
if (resolvedEntitySet === undefined) {
|
|
100
|
+
throw new Error(`createDataset: source "${descriptor.id}" (odata) requires locator.entitySet or locator.layerId`);
|
|
101
|
+
}
|
|
102
|
+
const basePath = url ? extractOdataBasePath(url) : "/odata";
|
|
103
|
+
return { entitySet: resolvedEntitySet, basePath };
|
|
104
|
+
}
|
|
105
|
+
function extractOdataBasePath(url) {
|
|
106
|
+
try {
|
|
107
|
+
const parsed = new URL(url);
|
|
108
|
+
const pathname = trimTrailingSlashes(parsed.pathname);
|
|
109
|
+
return pathname === "" ? "/odata" : pathname;
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
return url.startsWith("/") ? trimTrailingSlashes(url) || "/odata" : `/${trimTrailingSlashes(url)}`;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function assertExecutableOdataArtifact(adapter, compiled, operation) {
|
|
116
|
+
if (compiled.compiler !== "odata-v4-protocol-query-v1") {
|
|
117
|
+
throw new TypeError("odata: protocol module requires an odata-v4-protocol-query-v1 artifact");
|
|
118
|
+
}
|
|
119
|
+
if (compiled.entitySet !== adapter.entitySet) {
|
|
120
|
+
throw new TypeError("odata: compiled entitySet does not match the discovered protocol handle");
|
|
121
|
+
}
|
|
122
|
+
if (compiled.operation !== operation) {
|
|
123
|
+
throw new TypeError("odata: compiled operation does not match the requested protocol operation");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Recover the caller-visible queryAll ceiling from the compiler-owned
|
|
128
|
+
* lookahead row and reject any runtime context that does not describe the
|
|
129
|
+
* same bounded request. This runs before the adapter performs I/O.
|
|
130
|
+
*/
|
|
131
|
+
function resolveOdataQueryAllLogicalLimit(compiled, requestedLimit) {
|
|
132
|
+
if (requestedLimit !== undefined && (!Number.isSafeInteger(requestedLimit) || requestedLimit < 0)) {
|
|
133
|
+
throw new TypeError("odata: queryAll logical limit must be a non-negative safe integer");
|
|
134
|
+
}
|
|
135
|
+
if (compiled.top === undefined) {
|
|
136
|
+
if (requestedLimit !== undefined) {
|
|
137
|
+
throw new TypeError("odata: queryAll compiled top does not match the logical limit");
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
141
|
+
if (!Number.isSafeInteger(compiled.top) || compiled.top < 1) {
|
|
142
|
+
throw new TypeError("odata: queryAll compiled top must contain one lookahead row");
|
|
143
|
+
}
|
|
144
|
+
const compiledLogicalLimit = compiled.top - 1;
|
|
145
|
+
if (requestedLimit !== undefined && requestedLimit !== compiledLogicalLimit) {
|
|
146
|
+
throw new TypeError("odata: queryAll compiled top does not match the logical limit");
|
|
147
|
+
}
|
|
148
|
+
return requestedLimit ?? compiledLogicalLimit;
|
|
149
|
+
}
|
|
150
|
+
function odataParamsFromCompiled(compiled, count, signal) {
|
|
151
|
+
return {
|
|
152
|
+
...(compiled.filter !== undefined ? { filter: compiled.filter } : {}),
|
|
153
|
+
...(compiled.select !== undefined ? { select: compiled.select } : {}),
|
|
154
|
+
...(compiled.expand !== undefined ? { expand: compiled.expand } : {}),
|
|
155
|
+
...(compiled.orderBy !== undefined ? { orderBy: compiled.orderBy } : {}),
|
|
156
|
+
...(compiled.skip !== undefined ? { skip: compiled.skip } : {}),
|
|
157
|
+
...(compiled.top !== undefined ? { top: compiled.top } : {}),
|
|
158
|
+
...(count ? { count: true } : {}),
|
|
159
|
+
...(signal ? { signal } : {}),
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/** Internal shared result projection used by query execution and OData streaming. */
|
|
163
|
+
export function odataProtocolResultFromPage(descriptor, page, fields, returnGeometry, geometryColumn) {
|
|
164
|
+
const features = page.rows.map((row) => odataRowToFeature(row, descriptor, returnGeometry, geometryColumn));
|
|
165
|
+
const exceededTransferLimit = typeof page.totalCount === "number" ? features.length < page.totalCount : Boolean(page.nextLink);
|
|
166
|
+
return {
|
|
167
|
+
features,
|
|
168
|
+
exceededTransferLimit,
|
|
169
|
+
...(typeof page.totalCount === "number" ? { totalCount: page.totalCount } : {}),
|
|
170
|
+
...(fields.length > 0 ? { fields } : {}),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
function odataRowToFeature(row, descriptor, returnGeometry, geometryColumn) {
|
|
174
|
+
const geometryKey = geometryColumn ??
|
|
175
|
+
descriptor.schema?.fields?.find((field) => field.type === "esriFieldTypeGeometry")?.name ??
|
|
176
|
+
findGeometryKey(row);
|
|
177
|
+
if (geometryKey && row[geometryKey] !== undefined) {
|
|
178
|
+
const { [geometryKey]: geometry, ...attributes } = row;
|
|
179
|
+
return {
|
|
180
|
+
attributes: attributes,
|
|
181
|
+
geometry: returnGeometry === false ? null : (geometry ?? null),
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
return { attributes: row, geometry: null };
|
|
185
|
+
}
|
|
186
|
+
function findGeometryKey(row) {
|
|
187
|
+
for (const key of Object.keys(row)) {
|
|
188
|
+
const lower = key.toLowerCase();
|
|
189
|
+
if (lower === "geometry" || lower === "geography" || lower === "shape")
|
|
190
|
+
return key;
|
|
191
|
+
}
|
|
192
|
+
return undefined;
|
|
193
|
+
}
|
|
194
|
+
function applyLimit(features, limit) {
|
|
195
|
+
if (typeof limit !== "number" || limit < 0 || features.length <= limit) {
|
|
196
|
+
return { features, exceededTransferLimit: false };
|
|
197
|
+
}
|
|
198
|
+
return { features: features.slice(0, limit), exceededTransferLimit: true };
|
|
199
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lightweight deterministic OData v4 compiler.
|
|
3
|
+
*
|
|
4
|
+
* Kept separate from the semantic OData compiler so importing the public
|
|
5
|
+
* `odataProtocolModule()` does not pull the larger semantic compiler graph
|
|
6
|
+
* into contract-only bundles.
|
|
7
|
+
*/
|
|
8
|
+
import type { ProtocolModuleQueryCompileInput, ProtocolModuleQueryOperation } from "../contract/protocol-module.js";
|
|
9
|
+
import type { CanonicalQuery, OdataCompiledQueryV1, OdataProtocolCompiledQueryV1, QueryIrSourceIdentity } from "./types.js";
|
|
10
|
+
/** Compile canonical query IR to a deterministic OData v4 entity-set request. */
|
|
11
|
+
export declare function compileOdataQuery(source: QueryIrSourceIdentity, query: CanonicalQuery): OdataCompiledQueryV1;
|
|
12
|
+
/**
|
|
13
|
+
* The deterministic compiler hook installed on the first-party OData
|
|
14
|
+
* ProtocolModule. Planner dispatch and module consumers call this exact
|
|
15
|
+
* object, while runtime authority remains outside the compiler.
|
|
16
|
+
*/
|
|
17
|
+
export declare const odataProtocolQueryCompiler: Readonly<{
|
|
18
|
+
kind: "odata";
|
|
19
|
+
compile(input: ProtocolModuleQueryCompileInput<QueryIrSourceIdentity, CanonicalQuery>): OdataProtocolCompiledQueryV1;
|
|
20
|
+
}>;
|
|
21
|
+
/** Bind a legacy wire request to the exact operation authorized to execute it. */
|
|
22
|
+
export declare function bindOdataProtocolQueryOperation(compiled: OdataCompiledQueryV1, operation: ProtocolModuleQueryOperation): OdataProtocolCompiledQueryV1;
|
|
23
|
+
//# sourceMappingURL=odata-v1.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"odata-v1.d.ts","sourceRoot":"","sources":["../../../src/query-planner/odata-v1.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,+BAA+B,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAIpH,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACpB,4BAA4B,EAC5B,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAGpB,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,qBAAqB,EAAE,KAAK,EAAE,cAAc,GAAG,oBAAoB,CAqH5G;AAED;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;;mBAEtB,+BAA+B,CAAC,qBAAqB,EAAE,cAAc,CAAC,GAAG,4BAA4B;EAGpH,CAAC;AAEH,kFAAkF;AAClF,wBAAgB,+BAA+B,CAC7C,QAAQ,EAAE,oBAAoB,EAC9B,SAAS,EAAE,4BAA4B,GACtC,4BAA4B,CAsB9B"}
|