@honua/react 0.1.0-beta.0 → 0.1.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contract/discovery.d.ts +231 -0
- package/contract/discovery.d.ts.map +1 -0
- package/contract/discovery.js +554 -0
- package/contract/edit-sketch.d.ts +8 -0
- package/contract/edit-sketch.d.ts.map +1 -1
- package/contract/edit-sketch.js +15 -0
- package/contract/edit-snapping.d.ts +160 -0
- package/contract/edit-snapping.d.ts.map +1 -0
- package/contract/edit-snapping.js +675 -0
- package/contract/generated/projjson-v0.7-crs-validator.d.ts +35 -0
- package/contract/generated/projjson-v0.7-crs-validator.d.ts.map +1 -0
- package/contract/generated/projjson-v0.7-crs-validator.js +3941 -0
- package/contract/index.d.ts +11 -2
- package/contract/index.d.ts.map +1 -1
- package/contract/index.js +4 -1
- package/contract/pmtiles.d.ts +31 -0
- package/contract/pmtiles.d.ts.map +1 -1
- package/contract/pmtiles.js +60 -20
- package/contract/protocol-module.d.ts +70 -0
- package/contract/protocol-module.d.ts.map +1 -0
- package/contract/protocol-module.js +1 -0
- package/contract/schema-envelope.d.ts +26 -0
- package/contract/schema-envelope.d.ts.map +1 -0
- package/contract/schema-envelope.js +25 -0
- package/contract/schema.d.ts +582 -0
- package/contract/schema.d.ts.map +1 -0
- package/contract/schema.js +2483 -0
- package/contract/source-capability-support.d.ts +6 -0
- package/contract/source-capability-support.d.ts.map +1 -0
- package/contract/source-capability-support.js +154 -0
- package/contract/source.d.ts +35 -17
- package/contract/source.d.ts.map +1 -1
- package/contract/source.js +267 -71
- package/contract/types.d.ts +140 -4
- package/contract/types.d.ts.map +1 -1
- package/contract/types.js +6 -14
- package/core/bounded-json.d.ts +4 -0
- package/core/bounded-json.d.ts.map +1 -0
- package/core/bounded-json.js +38 -0
- package/core/cache-state.d.ts +9 -0
- package/core/cache-state.d.ts.map +1 -1
- package/core/cache-state.js +10 -0
- package/core/capabilities-xml.d.ts +33 -0
- package/core/capabilities-xml.d.ts.map +1 -0
- package/core/capabilities-xml.js +331 -0
- package/core/client.d.ts +4 -1
- package/core/client.d.ts.map +1 -1
- package/core/client.js +115 -29
- package/core/error-classifications.d.ts +153 -0
- package/core/error-classifications.d.ts.map +1 -0
- package/core/error-classifications.js +140 -0
- package/core/error-code-registry.d.ts +158 -0
- package/core/error-code-registry.d.ts.map +1 -0
- package/core/error-code-registry.js +143 -0
- package/core/error-envelope.d.ts +68 -0
- package/core/error-envelope.d.ts.map +1 -0
- package/core/error-envelope.js +357 -0
- package/core/errors.d.ts +45 -29
- package/core/errors.d.ts.map +1 -1
- package/core/errors.js +97 -50
- package/core/geoparquet-sql.d.ts +30 -2
- package/core/geoparquet-sql.d.ts.map +1 -1
- package/core/geoparquet-sql.js +38 -3
- package/core/odata-key-path.d.ts +12 -0
- package/core/odata-key-path.d.ts.map +1 -0
- package/core/odata-key-path.js +28 -0
- package/core/odata-write-codec.d.ts +66 -0
- package/core/odata-write-codec.d.ts.map +1 -0
- package/core/odata-write-codec.js +1083 -0
- package/core/odata.d.ts +59 -7
- package/core/odata.d.ts.map +1 -1
- package/core/odata.js +431 -99
- package/core/ogc-features.d.ts.map +1 -1
- package/core/ogc-features.js +3 -0
- package/core/ogc-maps.d.ts +7 -0
- package/core/ogc-maps.d.ts.map +1 -1
- package/core/ogc-maps.js +46 -7
- package/core/ogc-processes.d.ts +2 -1
- package/core/ogc-processes.d.ts.map +1 -1
- package/core/ogc-processes.js +33 -5
- package/core/ogc-records.d.ts +9 -0
- package/core/ogc-records.d.ts.map +1 -1
- package/core/ogc-records.js +78 -29
- package/core/ogc-tiles.d.ts +10 -1
- package/core/ogc-tiles.d.ts.map +1 -1
- package/core/ogc-tiles.js +56 -17
- package/core/path-utils.d.ts +9 -0
- package/core/path-utils.d.ts.map +1 -1
- package/core/path-utils.js +19 -0
- package/core/protocol-transport.d.ts +1 -0
- package/core/protocol-transport.d.ts.map +1 -1
- package/core/request-pipeline.d.ts.map +1 -1
- package/core/request-pipeline.js +1 -1
- package/core/spatial-filter.d.ts +8 -4
- package/core/spatial-filter.d.ts.map +1 -1
- package/core/spatial-filter.js +206 -16
- package/core/stac-static.d.ts +6 -2
- package/core/stac-static.d.ts.map +1 -1
- package/core/stac-static.js +260 -69
- package/core/surfaces.d.ts.map +1 -1
- package/core/surfaces.js +69 -5
- package/core/types.d.ts +125 -7
- package/core/types.d.ts.map +1 -1
- package/core/wfs-capabilities.d.ts +2 -0
- package/core/wfs-capabilities.d.ts.map +1 -1
- package/core/wfs-capabilities.js +8 -1
- package/core/wfs.d.ts.map +1 -1
- package/core/wfs.js +10 -0
- package/core/wms-capabilities.d.ts +56 -84
- package/core/wms-capabilities.d.ts.map +1 -1
- package/core/wms-capabilities.js +212 -509
- package/core/wmts-capabilities.d.ts +62 -62
- package/core/wmts-capabilities.d.ts.map +1 -1
- package/core/wmts-capabilities.js +224 -371
- package/esri-compat/editor.d.ts +8 -0
- package/esri-compat/editor.d.ts.map +1 -1
- package/esri-compat/editor.js +13 -0
- package/esri-compat/feature-layer.d.ts +2 -0
- package/esri-compat/feature-layer.d.ts.map +1 -1
- package/esri-compat/feature-layer.js +1 -0
- package/esri-compat/layer-list.d.ts +11 -0
- package/esri-compat/layer-list.d.ts.map +1 -1
- package/esri-compat/layer-list.js +49 -0
- package/esri-compat/legend.d.ts +10 -0
- package/esri-compat/legend.d.ts.map +1 -1
- package/esri-compat/legend.js +27 -0
- package/esri-compat/portal.d.ts +197 -0
- package/esri-compat/portal.d.ts.map +1 -0
- package/esri-compat/portal.js +251 -0
- package/esri-compat/renderer-objects.d.ts +40 -0
- package/esri-compat/renderer-objects.d.ts.map +1 -0
- package/esri-compat/renderer-objects.js +62 -0
- package/esri-compat/sketch.d.ts +43 -0
- package/esri-compat/sketch.d.ts.map +1 -1
- package/esri-compat/sketch.js +46 -0
- package/esri-compat/snapping.d.ts +43 -0
- package/esri-compat/snapping.d.ts.map +1 -0
- package/esri-compat/snapping.js +45 -0
- package/esri-compat/url.d.ts.map +1 -1
- package/esri-compat/url.js +1 -1
- package/esri-compat/widget-host.d.ts +84 -0
- package/esri-compat/widget-host.d.ts.map +1 -0
- package/esri-compat/widget-host.js +159 -0
- package/filter-registry/index.d.ts +145 -0
- package/filter-registry/index.d.ts.map +1 -0
- package/filter-registry/index.js +531 -0
- package/generated-app/errors.d.ts +18 -2
- package/generated-app/errors.d.ts.map +1 -1
- package/generated-app/errors.js +44 -11
- package/map/automatic-mount-integration.d.ts +134 -0
- package/map/automatic-mount-integration.d.ts.map +1 -0
- package/map/automatic-mount-integration.js +305 -0
- package/map/automatic-source-strategy.d.ts +125 -0
- package/map/automatic-source-strategy.d.ts.map +1 -0
- package/map/automatic-source-strategy.js +494 -0
- package/map/data-to-map-bridge.d.ts +293 -0
- package/map/data-to-map-bridge.d.ts.map +1 -0
- package/map/data-to-map-bridge.js +817 -0
- package/map/geojson-projection.d.ts +33 -0
- package/map/geojson-projection.d.ts.map +1 -0
- package/map/geojson-projection.js +118 -0
- package/map/index.d.ts +14 -0
- package/map/index.d.ts.map +1 -1
- package/map/index.js +8 -0
- package/map/raster-source-spec.d.ts +30 -0
- package/map/raster-source-spec.d.ts.map +1 -0
- package/map/raster-source-spec.js +190 -0
- package/map/raster-source-strategy.d.ts +65 -0
- package/map/raster-source-strategy.d.ts.map +1 -0
- package/map/raster-source-strategy.js +232 -0
- package/map/source-to-maplibre.d.ts +91 -0
- package/map/source-to-maplibre.d.ts.map +1 -0
- package/map/source-to-maplibre.js +454 -0
- package/map/temporal-playback.d.ts +139 -0
- package/map/temporal-playback.d.ts.map +1 -0
- package/map/temporal-playback.js +247 -0
- package/package.json +14 -1
- package/query-planner/canonical.d.ts +7 -0
- package/query-planner/canonical.d.ts.map +1 -0
- package/query-planner/canonical.js +145 -0
- package/query-planner/cql2-json.d.ts +17 -0
- package/query-planner/cql2-json.d.ts.map +1 -0
- package/query-planner/cql2-json.js +646 -0
- package/query-planner/diagnostics.d.ts +35 -0
- package/query-planner/diagnostics.d.ts.map +1 -0
- package/query-planner/diagnostics.js +373 -0
- package/query-planner/duckdb.d.ts +79 -0
- package/query-planner/duckdb.d.ts.map +1 -0
- package/query-planner/duckdb.js +758 -0
- package/query-planner/execution-context.d.ts +5 -0
- package/query-planner/execution-context.d.ts.map +1 -0
- package/query-planner/execution-context.js +50 -0
- package/query-planner/executor.d.ts +5 -0
- package/query-planner/executor.d.ts.map +1 -0
- package/query-planner/executor.js +223 -0
- package/query-planner/geoservices.d.ts +91 -0
- package/query-planner/geoservices.d.ts.map +1 -0
- package/query-planner/geoservices.js +667 -0
- package/query-planner/grpc.d.ts +100 -0
- package/query-planner/grpc.d.ts.map +1 -0
- package/query-planner/grpc.js +736 -0
- package/query-planner/index.d.ts +44 -0
- package/query-planner/index.d.ts.map +1 -0
- package/query-planner/index.js +30 -0
- package/query-planner/ir.d.ts +20 -0
- package/query-planner/ir.d.ts.map +1 -0
- package/query-planner/ir.js +417 -0
- package/query-planner/local-aggregate.d.ts +5 -0
- package/query-planner/local-aggregate.d.ts.map +1 -0
- package/query-planner/local-aggregate.js +126 -0
- package/query-planner/odata.d.ts +48 -0
- package/query-planner/odata.d.ts.map +1 -0
- package/query-planner/odata.js +662 -0
- package/query-planner/ogc-compiler.d.ts +55 -0
- package/query-planner/ogc-compiler.d.ts.map +1 -0
- package/query-planner/ogc-compiler.js +480 -0
- package/query-planner/ogc-features.d.ts +53 -0
- package/query-planner/ogc-features.d.ts.map +1 -0
- package/query-planner/ogc-features.js +617 -0
- package/query-planner/planner.d.ts +17 -0
- package/query-planner/planner.d.ts.map +1 -0
- package/query-planner/planner.js +818 -0
- package/query-planner/resource.d.ts +94 -0
- package/query-planner/resource.d.ts.map +1 -0
- package/query-planner/resource.js +526 -0
- package/query-planner/semantic-canonical.d.ts +15 -0
- package/query-planner/semantic-canonical.d.ts.map +1 -0
- package/query-planner/semantic-canonical.js +62 -0
- package/query-planner/semantic-compat.d.ts +10 -0
- package/query-planner/semantic-compat.d.ts.map +1 -0
- package/query-planner/semantic-compat.js +35 -0
- package/query-planner/semantic-compiler.d.ts +64 -0
- package/query-planner/semantic-compiler.d.ts.map +1 -0
- package/query-planner/semantic-compiler.js +81 -0
- package/query-planner/semantic-literals.d.ts +30 -0
- package/query-planner/semantic-literals.d.ts.map +1 -0
- package/query-planner/semantic-literals.js +133 -0
- package/query-planner/semantic-types.d.ts +265 -0
- package/query-planner/semantic-types.d.ts.map +1 -0
- package/query-planner/semantic-types.js +1 -0
- package/query-planner/semantic.d.ts +54 -0
- package/query-planner/semantic.d.ts.map +1 -0
- package/query-planner/semantic.js +1421 -0
- package/query-planner/types.d.ts +560 -0
- package/query-planner/types.d.ts.map +1 -0
- package/query-planner/types.js +49 -0
- package/query-planner/wfs-semantic.d.ts +58 -0
- package/query-planner/wfs-semantic.d.ts.map +1 -0
- package/query-planner/wfs-semantic.js +547 -0
- package/query-planner/wfs.d.ts +6 -0
- package/query-planner/wfs.d.ts.map +1 -0
- package/query-planner/wfs.js +71 -0
- package/react/external-map.d.ts +67 -0
- package/react/external-map.d.ts.map +1 -0
- package/react/external-map.js +63 -0
- package/react/honua-map.d.ts.map +1 -1
- package/react/honua-map.js +3 -2
- package/react/honua-source-layer.d.ts +110 -0
- package/react/honua-source-layer.d.ts.map +1 -0
- package/react/honua-source-layer.js +101 -0
- package/react/hooks.d.ts +28 -0
- package/react/hooks.d.ts.map +1 -1
- package/react/hooks.js +26 -4
- package/react/index.d.ts +8 -0
- package/react/index.d.ts.map +1 -1
- package/react/index.js +5 -0
- package/react/query-cache.d.ts +26 -4
- package/react/query-cache.d.ts.map +1 -1
- package/react/query-cache.js +51 -8
- package/react/selection.d.ts +177 -0
- package/react/selection.d.ts.map +1 -0
- package/react/selection.js +0 -0
- package/react/use-mounted-source.d.ts +69 -0
- package/react/use-mounted-source.d.ts.map +1 -0
- package/react/use-mounted-source.js +346 -0
- package/runtime/edit-snapping.d.ts +107 -0
- package/runtime/edit-snapping.d.ts.map +1 -0
- package/runtime/edit-snapping.js +190 -0
- package/runtime/errors.d.ts +3 -2
- package/runtime/errors.d.ts.map +1 -1
- package/runtime/errors.js +19 -2
- package/runtime/index.d.ts +6 -0
- package/runtime/index.d.ts.map +1 -1
- package/runtime/index.js +3 -0
- package/runtime/maplibre-renderer.d.ts +41 -0
- package/runtime/maplibre-renderer.d.ts.map +1 -0
- package/runtime/maplibre-renderer.js +322 -0
- package/runtime/query-tiles.d.ts +2 -1
- package/runtime/query-tiles.d.ts.map +1 -1
- package/runtime/query-tiles.js +6 -2
- package/runtime/source-bridge.d.ts +4 -4
- package/runtime/source-bridge.d.ts.map +1 -1
- package/runtime/source-bridge.js +9 -56
- package/runtime/style-interactions.d.ts +3 -2
- package/runtime/style-interactions.d.ts.map +1 -1
- package/runtime/style-interactions.js +11 -3
- package/runtime/terra-draw-sketch.d.ts +275 -0
- package/runtime/terra-draw-sketch.d.ts.map +1 -0
- package/runtime/terra-draw-sketch.js +404 -0
- package/source-capability-registry.d.ts +1 -0
- package/source-capability-registry.js +1 -0
- package/source-capability-types.d.ts +186 -0
- package/source-capability-types.js +7 -0
- package/style/index.d.ts +2 -0
- package/style/index.d.ts.map +1 -1
- package/style/index.js +2 -0
- package/style/renderers.d.ts +326 -0
- package/style/renderers.d.ts.map +1 -0
- package/style/renderers.js +517 -0
- package/webmap/convert-renderer.d.ts +24 -3
- package/webmap/convert-renderer.d.ts.map +1 -1
- package/webmap/convert-renderer.js +93 -112
- package/webmap/index.d.ts +1 -1
- package/webmap/index.d.ts.map +1 -1
- package/webmap/index.js +1 -1
|
@@ -0,0 +1,404 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* terra-draw binding for edit-sketch workflows.
|
|
3
|
+
*
|
|
4
|
+
* Adapts [terra-draw](https://terradraw.io) draw modes (point, linestring,
|
|
5
|
+
* polygon, rectangle, circle, freehand, select) to the renderer-neutral
|
|
6
|
+
* {@link EditSketchWorkflowModel}, so completed and edited geometries flow
|
|
7
|
+
* through the contract edit-session path — undo/redo, validation, and
|
|
8
|
+
* `applyEdits` submission all apply unchanged.
|
|
9
|
+
*
|
|
10
|
+
* terra-draw is an OPTIONAL peer dependency. This module never imports it at
|
|
11
|
+
* module scope: {@link bindTerraDrawSketch} accepts a duck-typed instance the
|
|
12
|
+
* app constructed itself, and {@link createTerraDrawSketch} pulls in
|
|
13
|
+
* `terra-draw` + `terra-draw-maplibre-gl-adapter` lazily via dynamic
|
|
14
|
+
* `import()` the first time it is called. Importing the SDK without terra-draw
|
|
15
|
+
* installed stays side-effect free.
|
|
16
|
+
*
|
|
17
|
+
* Snapping bridges through terra-draw's own pointer pipeline:
|
|
18
|
+
* {@link createTerraDrawSnapping} produces a function with terra-draw's
|
|
19
|
+
* `Snapping.toCustom` shape backed by the SDK {@link SnapIndex}, so the
|
|
20
|
+
* linestring / polygon / polyline modes snap against SDK-indexed features.
|
|
21
|
+
* Modes without a `snapping` option (point, rectangle, circle, freehand) keep
|
|
22
|
+
* terra-draw's native behavior; that seam is documented rather than papered
|
|
23
|
+
* over.
|
|
24
|
+
*
|
|
25
|
+
* @module
|
|
26
|
+
*/
|
|
27
|
+
import { resolveSnapCandidate, resolveSnappingConfig, } from "../contract/edit-snapping.js";
|
|
28
|
+
// ── Tool / mode mapping ───────────────────────────────────────
|
|
29
|
+
/**
|
|
30
|
+
* Canonical terra-draw mode for each {@link EditSketchTool}. `buffer` has no
|
|
31
|
+
* terra-draw equivalent (it needs geometry-service support) and maps to
|
|
32
|
+
* `undefined`.
|
|
33
|
+
*
|
|
34
|
+
* @experimental
|
|
35
|
+
*/
|
|
36
|
+
export const TERRA_DRAW_SKETCH_TOOL_MODES = Object.freeze({
|
|
37
|
+
point: "point",
|
|
38
|
+
line: "linestring",
|
|
39
|
+
polygon: "polygon",
|
|
40
|
+
rectangle: "rectangle",
|
|
41
|
+
circle: "circle",
|
|
42
|
+
buffer: undefined,
|
|
43
|
+
});
|
|
44
|
+
const MODE_TO_TOOL = Object.freeze({
|
|
45
|
+
point: "point",
|
|
46
|
+
marker: "point",
|
|
47
|
+
linestring: "line",
|
|
48
|
+
polyline: "line",
|
|
49
|
+
"freehand-linestring": "line",
|
|
50
|
+
polygon: "polygon",
|
|
51
|
+
freehand: "polygon",
|
|
52
|
+
sector: "polygon",
|
|
53
|
+
sensor: "polygon",
|
|
54
|
+
rectangle: "rectangle",
|
|
55
|
+
"angled-rectangle": "rectangle",
|
|
56
|
+
circle: "circle",
|
|
57
|
+
});
|
|
58
|
+
/**
|
|
59
|
+
* Map a terra-draw mode name to the {@link EditSketchTool} it produces.
|
|
60
|
+
* Freehand and sector/sensor modes draw polygons; marker draws points.
|
|
61
|
+
* Returns `undefined` for modes with no sketch-tool equivalent (`select`,
|
|
62
|
+
* `render`, `static`, custom modes).
|
|
63
|
+
*
|
|
64
|
+
* @experimental
|
|
65
|
+
*/
|
|
66
|
+
export function editSketchToolForTerraDrawMode(mode) {
|
|
67
|
+
return MODE_TO_TOOL[mode];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sketch-tool capability overrides for a workflow driven by terra-draw.
|
|
71
|
+
*
|
|
72
|
+
* The contract defaults mark `rectangle` and `circle` as unsupported because
|
|
73
|
+
* they need renderer support; terra-draw provides it. Pass the registered
|
|
74
|
+
* terra-draw mode names (defaults to every canonical drawing mode) and feed
|
|
75
|
+
* the result to `createEditSketchWorkflow({ sketchTools })`.
|
|
76
|
+
*
|
|
77
|
+
* @experimental
|
|
78
|
+
*/
|
|
79
|
+
export function terraDrawSketchToolCapabilities(modes) {
|
|
80
|
+
const registered = new Set(modes ?? Object.keys(MODE_TO_TOOL));
|
|
81
|
+
const capabilities = {};
|
|
82
|
+
for (const tool of ["point", "line", "polygon", "rectangle", "circle"]) {
|
|
83
|
+
const supported = [...registered].some((mode) => MODE_TO_TOOL[mode] === tool);
|
|
84
|
+
capabilities[tool] = supported
|
|
85
|
+
? "supported"
|
|
86
|
+
: { state: "unsupported", reason: `no terra-draw mode registered for the ${tool} tool` };
|
|
87
|
+
}
|
|
88
|
+
return capabilities;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Bind a terra-draw instance to an {@link EditSketchWorkflowModel} (REQ-001).
|
|
92
|
+
*
|
|
93
|
+
* Every terra-draw `finish` event (freshly drawn features and select-mode
|
|
94
|
+
* edits: dragged features, dragged/inserted/deleted coordinates) maps the
|
|
95
|
+
* finishing mode to an {@link EditSketchTool} and applies the feature geometry
|
|
96
|
+
* through `model.setSketchGeometry`, so workflow undo/redo and validation
|
|
97
|
+
* cover terra-draw edits. Deleting the tracked feature stages a `null`
|
|
98
|
+
* geometry through the same undoable path.
|
|
99
|
+
*
|
|
100
|
+
* The caller owns the terra-draw instance lifecycle (`start`/`stop`); the
|
|
101
|
+
* binding only attaches listeners and detaches them in `remove()`.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* const workflow = createEditSketchWorkflow({ source, sketchTools: terraDrawSketchToolCapabilities() });
|
|
106
|
+
* const handle = bindTerraDrawSketch(draw, { model: workflow });
|
|
107
|
+
* handle.setTool("polygon"); // draw.setMode("polygon") + workflow arming
|
|
108
|
+
* // ... user draws; workflow.snapshot().sketch.geometry now tracks terra-draw
|
|
109
|
+
* handle.undo(); // workflow history, mirrored back into terra-draw
|
|
110
|
+
* await workflow.submit(); // edit-session applyEdits path, unchanged
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* @experimental
|
|
114
|
+
*/
|
|
115
|
+
export function bindTerraDrawSketch(draw, options) {
|
|
116
|
+
const { model } = options;
|
|
117
|
+
const toolForMode = options.toolForMode ?? editSketchToolForTerraDrawMode;
|
|
118
|
+
const toolsByFeature = new Map();
|
|
119
|
+
let activeFeatureId;
|
|
120
|
+
let selectedFeatureId;
|
|
121
|
+
let syncing = false;
|
|
122
|
+
const featureById = (id) => draw.getSnapshotFeature?.(id) ?? draw.getSnapshot().find((feature) => feature.id === id);
|
|
123
|
+
const onFinish = (id, context) => {
|
|
124
|
+
if (syncing)
|
|
125
|
+
return;
|
|
126
|
+
const feature = featureById(id);
|
|
127
|
+
const mode = modeOf(feature, context);
|
|
128
|
+
const tool = toolForMode(mode);
|
|
129
|
+
const included = feature === undefined || (options.featureFilter?.(id, feature) ?? true);
|
|
130
|
+
let applied = false;
|
|
131
|
+
let geometry = null;
|
|
132
|
+
if (feature && tool && included) {
|
|
133
|
+
const cloned = cloneJsonLike(feature.geometry);
|
|
134
|
+
geometry = options.transformGeometry ? options.transformGeometry(cloned) : cloned;
|
|
135
|
+
applied = model.setSketchGeometry(tool, geometry).toolCapability(tool).state === "supported";
|
|
136
|
+
if (applied) {
|
|
137
|
+
const previousId = activeFeatureId;
|
|
138
|
+
activeFeatureId = id;
|
|
139
|
+
toolsByFeature.set(id, tool);
|
|
140
|
+
if (previousId !== undefined && previousId !== id) {
|
|
141
|
+
// The workflow model tracks a single sketch geometry, so a newly
|
|
142
|
+
// finished feature replaces the previous one: drop the stale
|
|
143
|
+
// draw-store feature instead of letting duplicates accumulate.
|
|
144
|
+
// No syncing guard needed: onChange ignores deletes whose ids do
|
|
145
|
+
// not include the (already swapped) activeFeatureId.
|
|
146
|
+
toolsByFeature.delete(previousId);
|
|
147
|
+
if (draw.removeFeatures && featureById(previousId))
|
|
148
|
+
draw.removeFeatures([previousId]);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
options.onFinish?.({ featureId: id, ...(tool ? { tool } : {}), mode, action: context.action, geometry, applied });
|
|
153
|
+
};
|
|
154
|
+
const onChange = (ids, type) => {
|
|
155
|
+
if (syncing || type !== "delete")
|
|
156
|
+
return;
|
|
157
|
+
if (activeFeatureId === undefined || !ids.includes(activeFeatureId))
|
|
158
|
+
return;
|
|
159
|
+
const removedId = activeFeatureId;
|
|
160
|
+
const tool = toolsByFeature.get(removedId) ?? model.snapshot().sketch.tool ?? "point";
|
|
161
|
+
model.setSketchGeometry(tool, null);
|
|
162
|
+
toolsByFeature.delete(removedId);
|
|
163
|
+
activeFeatureId = undefined;
|
|
164
|
+
if (selectedFeatureId === removedId)
|
|
165
|
+
selectedFeatureId = undefined;
|
|
166
|
+
options.onDelete?.(removedId);
|
|
167
|
+
};
|
|
168
|
+
const onSelect = (id) => {
|
|
169
|
+
selectedFeatureId = id;
|
|
170
|
+
options.onSelect?.(id);
|
|
171
|
+
};
|
|
172
|
+
const onDeselect = (id) => {
|
|
173
|
+
if (selectedFeatureId === id || selectedFeatureId === undefined)
|
|
174
|
+
selectedFeatureId = undefined;
|
|
175
|
+
options.onDeselect?.(id);
|
|
176
|
+
};
|
|
177
|
+
draw.on("finish", onFinish);
|
|
178
|
+
draw.on("change", onChange);
|
|
179
|
+
draw.on("select", onSelect);
|
|
180
|
+
draw.on("deselect", onDeselect);
|
|
181
|
+
const syncFromModel = () => {
|
|
182
|
+
if (!draw.removeFeatures || !draw.addFeatures)
|
|
183
|
+
return false;
|
|
184
|
+
const snapshot = model.snapshot();
|
|
185
|
+
const geometry = snapshot.sketch.geometry ?? null;
|
|
186
|
+
syncing = true;
|
|
187
|
+
try {
|
|
188
|
+
if (activeFeatureId !== undefined && featureById(activeFeatureId)) {
|
|
189
|
+
draw.removeFeatures([activeFeatureId]);
|
|
190
|
+
}
|
|
191
|
+
if (geometry === null) {
|
|
192
|
+
if (activeFeatureId !== undefined)
|
|
193
|
+
toolsByFeature.delete(activeFeatureId);
|
|
194
|
+
activeFeatureId = undefined;
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
const restored = options.restoreGeometry
|
|
198
|
+
? options.restoreGeometry(cloneJsonLike(geometry))
|
|
199
|
+
: cloneJsonLike(geometry);
|
|
200
|
+
const tool = (activeFeatureId !== undefined ? toolsByFeature.get(activeFeatureId) : undefined) ?? snapshot.sketch.tool;
|
|
201
|
+
const mode = tool ? (TERRA_DRAW_SKETCH_TOOL_MODES[tool] ?? "polygon") : "polygon";
|
|
202
|
+
const restoreId = activeFeatureId;
|
|
203
|
+
const feature = {
|
|
204
|
+
...(restoreId !== undefined ? { id: restoreId } : {}),
|
|
205
|
+
type: "Feature",
|
|
206
|
+
geometry: restored,
|
|
207
|
+
properties: { mode },
|
|
208
|
+
};
|
|
209
|
+
// Restoring after a delete leaves the id up to terra-draw: diff the
|
|
210
|
+
// snapshot to adopt the assigned id so the restored sketch stays
|
|
211
|
+
// tracked for later deletes/changes.
|
|
212
|
+
const priorIds = restoreId === undefined ? new Set(draw.getSnapshot().map((entry) => entry.id)) : undefined;
|
|
213
|
+
draw.addFeatures([feature]);
|
|
214
|
+
if (priorIds) {
|
|
215
|
+
const added = draw.getSnapshot().find((entry) => entry.id !== undefined && !priorIds.has(entry.id));
|
|
216
|
+
if (added?.id !== undefined) {
|
|
217
|
+
activeFeatureId = added.id;
|
|
218
|
+
if (tool)
|
|
219
|
+
toolsByFeature.set(added.id, tool);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
finally {
|
|
225
|
+
syncing = false;
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
get activeFeatureId() {
|
|
230
|
+
return activeFeatureId;
|
|
231
|
+
},
|
|
232
|
+
get selectedFeatureId() {
|
|
233
|
+
return selectedFeatureId;
|
|
234
|
+
},
|
|
235
|
+
setTool(tool) {
|
|
236
|
+
const capability = model.startSketch(tool);
|
|
237
|
+
const mode = TERRA_DRAW_SKETCH_TOOL_MODES[tool];
|
|
238
|
+
if (capability.state === "supported" && mode !== undefined)
|
|
239
|
+
draw.setMode(mode);
|
|
240
|
+
return capability;
|
|
241
|
+
},
|
|
242
|
+
select() {
|
|
243
|
+
draw.setMode("select");
|
|
244
|
+
},
|
|
245
|
+
cancel() {
|
|
246
|
+
draw.setMode("static");
|
|
247
|
+
},
|
|
248
|
+
undo() {
|
|
249
|
+
const undone = model.undo();
|
|
250
|
+
if (undone)
|
|
251
|
+
syncFromModel();
|
|
252
|
+
return undone;
|
|
253
|
+
},
|
|
254
|
+
redo() {
|
|
255
|
+
const redone = model.redo();
|
|
256
|
+
if (redone)
|
|
257
|
+
syncFromModel();
|
|
258
|
+
return redone;
|
|
259
|
+
},
|
|
260
|
+
syncFromModel,
|
|
261
|
+
remove() {
|
|
262
|
+
draw.off("finish", onFinish);
|
|
263
|
+
draw.off("change", onChange);
|
|
264
|
+
draw.off("select", onSelect);
|
|
265
|
+
draw.off("deselect", onDeselect);
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Build a snapping function with terra-draw's `Snapping.toCustom` shape backed
|
|
271
|
+
* by the SDK snapping engine (REQ-004).
|
|
272
|
+
*
|
|
273
|
+
* terra-draw exposes per-mode snapping on its linestring, polygon, and
|
|
274
|
+
* polyline modes; pass the result as `snapping.toCustom` when constructing
|
|
275
|
+
* those modes and every drawn vertex snaps against the {@link SnapIndex}
|
|
276
|
+
* with the SDK's deterministic candidate ordering. Point, rectangle, circle,
|
|
277
|
+
* and freehand modes do not accept a `snapping` option in terra-draw — for
|
|
278
|
+
* those, terra-draw's pointer pipeline has no custom-snapping seam, so only
|
|
279
|
+
* terra-draw-native behavior applies.
|
|
280
|
+
*
|
|
281
|
+
* @example
|
|
282
|
+
* ```ts
|
|
283
|
+
* const snap = createTerraDrawSnapping({ index, model: workflow });
|
|
284
|
+
* new TerraDrawPolygonMode({ snapping: { toCustom: snap } });
|
|
285
|
+
* ```
|
|
286
|
+
*
|
|
287
|
+
* @experimental
|
|
288
|
+
*/
|
|
289
|
+
export function createTerraDrawSnapping(options) {
|
|
290
|
+
const effectiveConfig = () => options.model && !options.config ? options.model.snappingConfig() : resolveSnappingConfig(options.config);
|
|
291
|
+
return (event, context) => {
|
|
292
|
+
const resolution = resolveSnapCandidate(options.index, {
|
|
293
|
+
point: { x: event.containerX, y: event.containerY },
|
|
294
|
+
position: [event.lng, event.lat],
|
|
295
|
+
project: (position) => context.project(position[0], position[1]),
|
|
296
|
+
}, effectiveConfig());
|
|
297
|
+
options.onResolve?.(resolution);
|
|
298
|
+
return resolution.candidate ? [resolution.candidate.position[0], resolution.candidate.position[1]] : undefined;
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
async function loadTerraDrawModules() {
|
|
302
|
+
let terraDraw;
|
|
303
|
+
try {
|
|
304
|
+
terraDraw = (await import("terra-draw"));
|
|
305
|
+
}
|
|
306
|
+
catch (cause) {
|
|
307
|
+
throw new Error("terra-draw-sketch: terra-draw is an optional peer dependency and is not installed. " +
|
|
308
|
+
"Install it with `npm i terra-draw terra-draw-maplibre-gl-adapter` to use createTerraDrawSketch().", { cause: cause instanceof Error ? cause : undefined });
|
|
309
|
+
}
|
|
310
|
+
let adapter;
|
|
311
|
+
try {
|
|
312
|
+
adapter = (await import("terra-draw-maplibre-gl-adapter"));
|
|
313
|
+
}
|
|
314
|
+
catch (cause) {
|
|
315
|
+
throw new Error("terra-draw-sketch: terra-draw-maplibre-gl-adapter is an optional peer dependency and is not installed. " +
|
|
316
|
+
"Install it with `npm i terra-draw-maplibre-gl-adapter` to use createTerraDrawSketch() on a MapLibre map.", { cause: cause instanceof Error ? cause : undefined });
|
|
317
|
+
}
|
|
318
|
+
return { terraDraw, adapter };
|
|
319
|
+
}
|
|
320
|
+
/** Default select-mode flags: every mode's features selectable and reshapeable. */
|
|
321
|
+
function defaultSelectFlags(modes) {
|
|
322
|
+
const flags = {};
|
|
323
|
+
for (const mode of modes) {
|
|
324
|
+
flags[mode] = {
|
|
325
|
+
feature: {
|
|
326
|
+
draggable: true,
|
|
327
|
+
coordinates: { draggable: true, midpoints: true, deletable: true },
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
return flags;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* One-call terra-draw sketch setup for a MapLibre map.
|
|
335
|
+
*
|
|
336
|
+
* Dynamically imports the optional `terra-draw` and
|
|
337
|
+
* `terra-draw-maplibre-gl-adapter` peers (throwing a descriptive error when
|
|
338
|
+
* either is missing), registers the canonical drawing modes (point,
|
|
339
|
+
* linestring, polygon, rectangle, circle, freehand, select), wires SDK
|
|
340
|
+
* snapping into the modes that accept a custom snapping hook, starts the
|
|
341
|
+
* instance, and returns it bound to the workflow model via
|
|
342
|
+
* {@link bindTerraDrawSketch}.
|
|
343
|
+
*
|
|
344
|
+
* Apps that need custom mode options should construct terra-draw themselves
|
|
345
|
+
* and call {@link bindTerraDrawSketch} directly.
|
|
346
|
+
*
|
|
347
|
+
* @experimental
|
|
348
|
+
*/
|
|
349
|
+
export async function createTerraDrawSketch(map, options) {
|
|
350
|
+
const { terraDraw, adapter } = await loadTerraDrawModules();
|
|
351
|
+
const snapping = options.snapping ? { toCustom: createTerraDrawSnapping(options.snapping) } : undefined;
|
|
352
|
+
const drawModes = ["point", "linestring", "polygon", "rectangle", "circle", "freehand"];
|
|
353
|
+
const modes = [
|
|
354
|
+
new terraDraw.TerraDrawPointMode(),
|
|
355
|
+
new terraDraw.TerraDrawLineStringMode(snapping ? { snapping } : {}),
|
|
356
|
+
new terraDraw.TerraDrawPolygonMode(snapping ? { snapping } : {}),
|
|
357
|
+
new terraDraw.TerraDrawRectangleMode(),
|
|
358
|
+
new terraDraw.TerraDrawCircleMode(),
|
|
359
|
+
new terraDraw.TerraDrawFreehandMode(),
|
|
360
|
+
new terraDraw.TerraDrawSelectMode({ flags: defaultSelectFlags(drawModes) }),
|
|
361
|
+
];
|
|
362
|
+
const draw = new terraDraw.TerraDraw({
|
|
363
|
+
adapter: new adapter.TerraDrawMapLibreGLAdapter({ map }),
|
|
364
|
+
modes,
|
|
365
|
+
});
|
|
366
|
+
draw.start();
|
|
367
|
+
const handle = bindTerraDrawSketch(draw, options);
|
|
368
|
+
return {
|
|
369
|
+
draw,
|
|
370
|
+
model: options.model,
|
|
371
|
+
get activeFeatureId() {
|
|
372
|
+
return handle.activeFeatureId;
|
|
373
|
+
},
|
|
374
|
+
get selectedFeatureId() {
|
|
375
|
+
return handle.selectedFeatureId;
|
|
376
|
+
},
|
|
377
|
+
setTool: (tool) => handle.setTool(tool),
|
|
378
|
+
select: () => handle.select(),
|
|
379
|
+
cancel: () => handle.cancel(),
|
|
380
|
+
undo: () => handle.undo(),
|
|
381
|
+
redo: () => handle.redo(),
|
|
382
|
+
syncFromModel: () => handle.syncFromModel(),
|
|
383
|
+
remove: () => handle.remove(),
|
|
384
|
+
stop() {
|
|
385
|
+
handle.remove();
|
|
386
|
+
draw.stop();
|
|
387
|
+
},
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
// ── Internal helpers ──────────────────────────────────────────
|
|
391
|
+
function modeOf(feature, context) {
|
|
392
|
+
const mode = feature?.properties?.mode;
|
|
393
|
+
return typeof mode === "string" ? mode : context.mode;
|
|
394
|
+
}
|
|
395
|
+
function cloneJsonLike(value) {
|
|
396
|
+
if (value === null || typeof value !== "object")
|
|
397
|
+
return value;
|
|
398
|
+
if (Array.isArray(value))
|
|
399
|
+
return value.map(cloneJsonLike);
|
|
400
|
+
const out = {};
|
|
401
|
+
for (const [key, entry] of Object.entries(value))
|
|
402
|
+
out[key] = cloneJsonLike(entry);
|
|
403
|
+
return out;
|
|
404
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { isRegisteredCapabilityProfile, matchesRegisteredCapabilityProfileSource } from "@honua/sdk/internal/source-capability-profile-verifier";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { isRegisteredCapabilityProfile, matchesRegisteredCapabilityProfileSource } from "@honua/sdk/internal/source-capability-profile-verifier";
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { JsonValue, ResolvedCrsDefinition, SourceProtocol } from "./contract/schema.js";
|
|
2
|
+
import type { Capability as BuiltInCapabilityId } from "./contract/types.js";
|
|
3
|
+
export declare const CAPABILITY_EVIDENCE_PROFILE_KIND: "honua.capability-evidence";
|
|
4
|
+
export declare const CAPABILITY_EVIDENCE_PROFILE_VERSION: "1.0";
|
|
5
|
+
export declare const CAPABILITY_EVIDENCE_FINGERPRINT_DOMAIN: "honua:capability-evidence:1.0";
|
|
6
|
+
export declare const CAPABILITY_SOURCE_ENDPOINT_FINGERPRINT_DOMAIN: "honua:capability-source-endpoint:1.0";
|
|
7
|
+
export declare const CAPABILITY_PROFILE_KIND: "honua.capabilities";
|
|
8
|
+
export declare const CAPABILITY_PROFILE_VERSION: "1.0";
|
|
9
|
+
export declare const CAPABILITY_PROFILE_FINGERPRINT_DOMAIN: "honua:capabilities:1.0";
|
|
10
|
+
export type ExtensionIdentifier = `${string}.${string}`;
|
|
11
|
+
export type Sha256 = `sha256:${string}`;
|
|
12
|
+
export type IsoInstant = string;
|
|
13
|
+
export type CapabilityId = BuiltInCapabilityId | ExtensionIdentifier;
|
|
14
|
+
export type CapabilityTruth = "supported" | "unsupported" | "unknown";
|
|
15
|
+
export type ObservedCapabilityTruth = CapabilityTruth | "not-observed";
|
|
16
|
+
export type CapabilityClaimEvidenceKind = "protocol-default" | "declaration";
|
|
17
|
+
export type CapabilityObservationEvidenceKind = "metadata" | "conformance" | "probe";
|
|
18
|
+
export type CapabilityEvidenceKind = CapabilityClaimEvidenceKind | CapabilityObservationEvidenceKind;
|
|
19
|
+
interface CapabilityEvidenceBase {
|
|
20
|
+
readonly truth: CapabilityTruth;
|
|
21
|
+
/**
|
|
22
|
+
* Stable evidence identity. Common credential-shaped forms are rejected, but
|
|
23
|
+
* callers must still treat accepted values as potentially sensitive and must
|
|
24
|
+
* not supply credentials, signed URLs, or secrets.
|
|
25
|
+
*/
|
|
26
|
+
readonly reference: string;
|
|
27
|
+
/** Evidence identity only; when present it must match the enclosing source profile. */
|
|
28
|
+
readonly sourceFingerprint?: Sha256;
|
|
29
|
+
}
|
|
30
|
+
export interface CapabilityClaimEvidence extends CapabilityEvidenceBase {
|
|
31
|
+
readonly kind: CapabilityClaimEvidenceKind;
|
|
32
|
+
readonly observedAt?: never;
|
|
33
|
+
readonly expiresAt?: never;
|
|
34
|
+
}
|
|
35
|
+
export interface CapabilityObservationEvidence extends CapabilityEvidenceBase {
|
|
36
|
+
readonly kind: CapabilityObservationEvidenceKind;
|
|
37
|
+
readonly observedAt: IsoInstant;
|
|
38
|
+
/** Exclusive freshness boundary. */
|
|
39
|
+
readonly expiresAt: IsoInstant;
|
|
40
|
+
}
|
|
41
|
+
export type CapabilityEvidence = CapabilityClaimEvidence | CapabilityObservationEvidence;
|
|
42
|
+
export type TopologicalSpatialPredicate = "equals" | "intersects" | "within" | "contains" | "disjoint" | "touches" | "overlaps" | "crosses";
|
|
43
|
+
export type DistanceSpatialPredicate = "within-distance" | "beyond-distance";
|
|
44
|
+
export type SpatialPredicate = TopologicalSpatialPredicate | "bbox-intersects" | DistanceSpatialPredicate;
|
|
45
|
+
export type TemporalPredicate = "before" | "after" | "during" | "time-intersects";
|
|
46
|
+
export type BuiltInFilterOperator = "eq" | "ne" | "lt" | "lte" | "gt" | "gte" | "in" | "between" | "is-null" | "is-not-null" | "like" | "and" | "or" | "not" | SpatialPredicate | TemporalPredicate;
|
|
47
|
+
export type FilterOperatorId = BuiltInFilterOperator | ExtensionIdentifier;
|
|
48
|
+
export type PaginationMode = "offset" | "cursor" | "next-link";
|
|
49
|
+
export type ExtensionMap = Readonly<Record<ExtensionIdentifier, JsonValue>>;
|
|
50
|
+
export interface CapabilityConstraints {
|
|
51
|
+
readonly inputFormats?: readonly string[];
|
|
52
|
+
readonly outputFormats?: readonly string[];
|
|
53
|
+
readonly filterOperators?: readonly FilterOperatorId[];
|
|
54
|
+
readonly spatialPredicates?: readonly SpatialPredicate[];
|
|
55
|
+
readonly temporalPredicates?: readonly TemporalPredicate[];
|
|
56
|
+
readonly supportedCrs?: readonly ResolvedCrsDefinition[];
|
|
57
|
+
readonly pagination?: {
|
|
58
|
+
readonly modes: readonly PaginationMode[];
|
|
59
|
+
readonly maxPageSize?: number;
|
|
60
|
+
};
|
|
61
|
+
readonly limits?: {
|
|
62
|
+
readonly maxRecords?: number;
|
|
63
|
+
readonly maxRequestBytes?: number;
|
|
64
|
+
readonly maxResponseBytes?: number;
|
|
65
|
+
};
|
|
66
|
+
/** Caller metadata. Sensitive keys/forms are rejected; credentials remain prohibited. */
|
|
67
|
+
readonly extensions?: ExtensionMap;
|
|
68
|
+
}
|
|
69
|
+
export type CapabilityRuntimeEnvironment = "browser" | "worker" | "node" | "edge" | ExtensionIdentifier;
|
|
70
|
+
/**
|
|
71
|
+
* Credential-free source endpoint coordinates used only to derive a digest.
|
|
72
|
+
* Query strings, fragments, URL user-info, and credential-shaped source ids
|
|
73
|
+
* are rejected before hashing and the raw coordinates are never transported.
|
|
74
|
+
*/
|
|
75
|
+
export interface CapabilitySourceEndpointIdentity {
|
|
76
|
+
readonly endpoint: string;
|
|
77
|
+
readonly protocol: SourceProtocol;
|
|
78
|
+
readonly sourceId?: string;
|
|
79
|
+
}
|
|
80
|
+
/** Static execution requirements retained in evidence and evaluated decisions. */
|
|
81
|
+
export interface CapabilityRequirements {
|
|
82
|
+
readonly environments?: readonly CapabilityRuntimeEnvironment[];
|
|
83
|
+
/** Structural package/runtime identifiers; credential values are prohibited. */
|
|
84
|
+
readonly peers?: readonly string[];
|
|
85
|
+
}
|
|
86
|
+
/** One normalized, cacheable claimed/observed entry. */
|
|
87
|
+
export interface CapabilityEvidenceEntry {
|
|
88
|
+
readonly id: CapabilityId;
|
|
89
|
+
readonly claimed: CapabilityTruth;
|
|
90
|
+
readonly observed: ObservedCapabilityTruth;
|
|
91
|
+
readonly evidence: readonly CapabilityEvidence[];
|
|
92
|
+
/** Structural scope identifiers only. Tokens and credentials are prohibited. */
|
|
93
|
+
readonly authorizationScopes?: readonly string[];
|
|
94
|
+
readonly constraints?: CapabilityConstraints;
|
|
95
|
+
readonly requirements?: CapabilityRequirements;
|
|
96
|
+
}
|
|
97
|
+
/** @deprecated Use {@link CapabilityEvidenceEntry}. */
|
|
98
|
+
export type CapabilityEvaluationEntry = CapabilityEvidenceEntry;
|
|
99
|
+
export interface CapabilityEvidenceProfileOptions {
|
|
100
|
+
/** SourceSchemaV2 SHA-256 identity. May be derived only from consistent evidence. */
|
|
101
|
+
readonly sourceFingerprint?: Sha256;
|
|
102
|
+
/** Required credential-free endpoint coordinates; only their derived digest is retained. */
|
|
103
|
+
readonly sourceEndpoint: CapabilitySourceEndpointIdentity;
|
|
104
|
+
}
|
|
105
|
+
export interface CapabilitySourceVerificationOptions {
|
|
106
|
+
/** Current SourceSchemaV2 SHA-256 identity. Must be paired with expectedSourceEndpoint. */
|
|
107
|
+
readonly expectedSourceFingerprint?: Sha256;
|
|
108
|
+
/** Current credential-free endpoint coordinates. Must be paired with expectedSourceFingerprint. */
|
|
109
|
+
readonly expectedSourceEndpoint?: CapabilitySourceEndpointIdentity;
|
|
110
|
+
}
|
|
111
|
+
/** Heavy, one-time validated transport/cache envelope for one source. */
|
|
112
|
+
export interface CapabilityEvidenceProfile {
|
|
113
|
+
readonly kind: typeof CAPABILITY_EVIDENCE_PROFILE_KIND;
|
|
114
|
+
readonly version: typeof CAPABILITY_EVIDENCE_PROFILE_VERSION;
|
|
115
|
+
readonly fingerprint: Sha256;
|
|
116
|
+
/** Required SourceSchemaV2 identity for cache invalidation and source binding. */
|
|
117
|
+
readonly sourceFingerprint: Sha256;
|
|
118
|
+
/** Required digest of normalized protocol/endpoint/source coordinates. */
|
|
119
|
+
readonly sourceEndpointFingerprint: Sha256;
|
|
120
|
+
readonly entries: readonly CapabilityEvidenceEntry[];
|
|
121
|
+
}
|
|
122
|
+
/** Dynamic policy for the canonical claimed/observed/effective evaluator. */
|
|
123
|
+
export interface CapabilityEvaluationPolicy {
|
|
124
|
+
/** Optional allow-list. An omitted list allows every evidence-supported entry. */
|
|
125
|
+
readonly allow?: readonly CapabilityId[];
|
|
126
|
+
/** Explicit deny-list. Denial wins when an id appears in both lists. */
|
|
127
|
+
readonly deny?: readonly CapabilityId[];
|
|
128
|
+
}
|
|
129
|
+
export interface CapabilityAuthorizationContext {
|
|
130
|
+
/** Structural scope identifiers; credential/token values are prohibited. */
|
|
131
|
+
readonly grantedScopes?: readonly string[];
|
|
132
|
+
/** Scopes the current principal is known not to be allowed to acquire. */
|
|
133
|
+
readonly deniedScopes?: readonly string[];
|
|
134
|
+
}
|
|
135
|
+
/** Dynamic inputs refreshed for each lightweight evaluation. */
|
|
136
|
+
export interface CapabilityEvaluationContext {
|
|
137
|
+
/** Explicit deterministic clock input. Omission makes observation freshness unknown. */
|
|
138
|
+
readonly evaluatedAt?: IsoInstant;
|
|
139
|
+
readonly policy?: CapabilityEvaluationPolicy;
|
|
140
|
+
readonly environment?: CapabilityRuntimeEnvironment;
|
|
141
|
+
/** Structural package/runtime identifiers; credential values are prohibited. */
|
|
142
|
+
readonly availablePeers?: readonly string[];
|
|
143
|
+
readonly authorization?: CapabilityAuthorizationContext;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Normalized caller-controlled context retained so transported decisions can
|
|
147
|
+
* be reverified. It is not a sanitizer; profiles remain potentially sensitive.
|
|
148
|
+
*/
|
|
149
|
+
export interface CapabilityEvaluationContextSnapshot {
|
|
150
|
+
readonly policy?: {
|
|
151
|
+
readonly allow?: readonly CapabilityId[];
|
|
152
|
+
readonly deny: readonly CapabilityId[];
|
|
153
|
+
};
|
|
154
|
+
readonly environment?: CapabilityRuntimeEnvironment;
|
|
155
|
+
readonly availablePeers: readonly string[];
|
|
156
|
+
readonly authorization: {
|
|
157
|
+
readonly grantedScopes: readonly string[];
|
|
158
|
+
readonly deniedScopes: readonly string[];
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
export type EffectiveCapabilityState = "supported" | "unsupported" | "unknown" | "policy-disabled" | "peer-unavailable" | "authorization-required" | "authorization-denied";
|
|
162
|
+
/** Stable codes; suffixed forms name the missing environment, peer, or scope. */
|
|
163
|
+
export type CapabilityDecisionReason = "supported-by-claim-and-observation" | "unsupported-by-claim" | "unsupported-by-observation" | "claim-unknown" | "observation-unknown" | "observation-not-observed" | "freshness-not-evaluated" | "evidence-not-yet-current" | "evidence-stale" | "policy-disabled" | `environment-unavailable:${string}` | `peer-unavailable:${string}` | `authorization-required:${string}` | `authorization-denied:${string}`;
|
|
164
|
+
export interface CapabilityDecision extends CapabilityEvidenceEntry {
|
|
165
|
+
readonly effective: EffectiveCapabilityState;
|
|
166
|
+
readonly reasons: readonly CapabilityDecisionReason[];
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Auditable evaluated truth derived from one evidence envelope and one dynamic
|
|
170
|
+
* context. Caller-controlled values make serialized profiles potentially sensitive.
|
|
171
|
+
*/
|
|
172
|
+
export interface CapabilityProfile {
|
|
173
|
+
readonly kind: typeof CAPABILITY_PROFILE_KIND;
|
|
174
|
+
readonly version: typeof CAPABILITY_PROFILE_VERSION;
|
|
175
|
+
readonly fingerprint: Sha256;
|
|
176
|
+
readonly evidenceFingerprint: Sha256;
|
|
177
|
+
readonly sourceFingerprint: Sha256;
|
|
178
|
+
readonly sourceEndpointFingerprint: Sha256;
|
|
179
|
+
readonly evaluatedAt: IsoInstant | null;
|
|
180
|
+
/** Exclusive conservative boundary; null means no freshness window was established. */
|
|
181
|
+
readonly validUntil: IsoInstant | null;
|
|
182
|
+
readonly context: CapabilityEvaluationContextSnapshot;
|
|
183
|
+
readonly entries: readonly CapabilityDecision[];
|
|
184
|
+
}
|
|
185
|
+
export {};
|
|
186
|
+
//# sourceMappingURL=source-capability-types.d.ts.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const CAPABILITY_EVIDENCE_PROFILE_KIND = "honua.capability-evidence";
|
|
2
|
+
export const CAPABILITY_EVIDENCE_PROFILE_VERSION = "1.0";
|
|
3
|
+
export const CAPABILITY_EVIDENCE_FINGERPRINT_DOMAIN = "honua:capability-evidence:1.0";
|
|
4
|
+
export const CAPABILITY_SOURCE_ENDPOINT_FINGERPRINT_DOMAIN = "honua:capability-source-endpoint:1.0";
|
|
5
|
+
export const CAPABILITY_PROFILE_KIND = "honua.capabilities";
|
|
6
|
+
export const CAPABILITY_PROFILE_VERSION = "1.0";
|
|
7
|
+
export const CAPABILITY_PROFILE_FINGERPRINT_DOMAIN = "honua:capabilities:1.0";
|
package/style/index.d.ts
CHANGED
|
@@ -22,4 +22,6 @@ export { isHonuaSource, isFeatureServiceSource, isMapServiceSource, isOgcFeature
|
|
|
22
22
|
export type { HonuaSourceBase, HonuaFeatureServiceSourceSpecification, HonuaMapServiceSourceSpecification, HonuaOgcFeaturesSourceSpecification, HonuaWmsSourceSpecification, HonuaWmtsSourceSpecification, HonuaSourceSpecification, HonuaLayerSpecification, HonuaStyleSpecification, ParsedOgcFeaturesUrl, StyleValidationError, } from "./specification.js";
|
|
23
23
|
export { createSources } from "./factory.js";
|
|
24
24
|
export type { ResolvedSource } from "./factory.js";
|
|
25
|
+
export { classBreaksRenderer, clusterRenderer, heatmapRenderer, isRenderer, rendererFromJSON, uniqueValueRenderer, } from "./renderers.js";
|
|
26
|
+
export type { ClassBreakEntry, ClassBreaksRenderer, ClassBreaksRendererDescriptor, ClassBreaksRendererOptions, ClusterRenderer, ClusterRendererDescriptor, ClusterRendererOptions, ClusterStep, HeatmapColorStop, HeatmapRenderer, HeatmapRendererDescriptor, HeatmapRendererOptions, Renderer, RendererDescriptor, RendererGeometryType, RendererLayerFragment, RendererLegendItem, RendererStyle, UniqueValueEntry, UniqueValueRenderer, UniqueValueRendererDescriptor, UniqueValueRendererOptions, } from "./renderers.js";
|
|
25
27
|
//# sourceMappingURL=index.d.ts.map
|
package/style/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/style/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,eAAe,EACf,sCAAsC,EACtC,kCAAkC,EAClC,mCAAmC,EACnC,2BAA2B,EAC3B,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/style/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,aAAa,EACb,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,YAAY,EACZ,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,eAAe,EACf,sCAAsC,EACtC,kCAAkC,EAClC,mCAAmC,EACnC,2BAA2B,EAC3B,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,EACL,mBAAmB,EACnB,eAAe,EACf,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,EAC1B,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,WAAW,EACX,gBAAgB,EAChB,eAAe,EACf,yBAAyB,EACzB,sBAAsB,EACtB,QAAQ,EACR,kBAAkB,EAClB,oBAAoB,EACpB,qBAAqB,EACrB,kBAAkB,EAClB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,6BAA6B,EAC7B,0BAA0B,GAC3B,MAAM,gBAAgB,CAAC"}
|
package/style/index.js
CHANGED
|
@@ -20,5 +20,7 @@
|
|
|
20
20
|
*/
|
|
21
21
|
export { isHonuaSource, isFeatureServiceSource, isMapServiceSource, isOgcFeaturesSource, isWmsSource, isWmtsSource, parseOgcFeaturesUrl, validateHonuaStyle, } from "./specification.js";
|
|
22
22
|
export { createSources } from "./factory.js";
|
|
23
|
+
// First-class renderer objects (issue #497). All @experimental.
|
|
24
|
+
export { classBreaksRenderer, clusterRenderer, heatmapRenderer, isRenderer, rendererFromJSON, uniqueValueRenderer, } from "./renderers.js";
|
|
23
25
|
// Feature Service and Map Service URL parsers are exported from
|
|
24
26
|
// esri-compat/url.ts via the main index.ts barrel — no re-export needed here.
|