@geospatial-sdk/core 0.0.5-alpha.9 → 0.0.5-dev.0.sha-bfaf14b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +38 -5
  2. package/dist/constant/projections.d.ts +2 -0
  3. package/dist/constant/projections.d.ts.map +1 -0
  4. package/dist/constant/projections.js +1 -0
  5. package/dist/index.d.ts +7 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +7 -3
  8. package/dist/model/events.d.ts +86 -0
  9. package/dist/model/events.d.ts.map +1 -0
  10. package/dist/model/events.js +37 -0
  11. package/dist/model/index.d.ts +9 -2
  12. package/dist/model/index.d.ts.map +1 -1
  13. package/dist/model/index.js +9 -2
  14. package/dist/model/map-context-diff.d.ts +11 -3
  15. package/dist/model/map-context-diff.d.ts.map +1 -1
  16. package/dist/model/map-context.d.ts +174 -22
  17. package/dist/model/map-context.d.ts.map +1 -1
  18. package/dist/model/resolved-map-state.d.ts +49 -0
  19. package/dist/model/resolved-map-state.d.ts.map +1 -0
  20. package/dist/model/resolved-map-state.js +1 -0
  21. package/dist/model/style.d.ts +3 -0
  22. package/dist/model/style.d.ts.map +1 -0
  23. package/dist/model/style.js +1 -0
  24. package/dist/utils/hash.d.ts +2 -0
  25. package/dist/utils/hash.d.ts.map +1 -0
  26. package/dist/utils/hash.js +28 -0
  27. package/dist/utils/index.d.ts +12 -4
  28. package/dist/utils/index.d.ts.map +1 -1
  29. package/dist/utils/index.js +12 -4
  30. package/dist/utils/map-context-diff.d.ts +1 -1
  31. package/dist/utils/map-context-diff.d.ts.map +1 -1
  32. package/dist/utils/map-context-diff.js +19 -11
  33. package/dist/utils/map-context-layer.d.ts +13 -0
  34. package/dist/utils/map-context-layer.d.ts.map +1 -0
  35. package/dist/utils/map-context-layer.js +44 -0
  36. package/dist/utils/map-context.d.ts +48 -4
  37. package/dist/utils/map-context.d.ts.map +1 -1
  38. package/dist/utils/map-context.js +80 -29
  39. package/dist/utils/style.d.ts +4 -0
  40. package/dist/utils/style.d.ts.map +1 -0
  41. package/dist/utils/style.js +68 -0
  42. package/dist/utils/view.d.ts +25 -0
  43. package/dist/utils/view.d.ts.map +1 -0
  44. package/dist/utils/view.js +126 -0
  45. package/lib/constant/projections.ts +1 -0
  46. package/lib/index.ts +8 -3
  47. package/lib/model/events.ts +113 -0
  48. package/lib/model/index.ts +10 -2
  49. package/lib/model/map-context-diff.ts +12 -3
  50. package/lib/model/map-context.ts +219 -26
  51. package/lib/model/resolved-map-state.ts +67 -0
  52. package/lib/model/style.ts +3 -0
  53. package/lib/utils/freeze.test.ts +1 -1
  54. package/lib/utils/hash.test.ts +180 -0
  55. package/lib/utils/hash.ts +28 -0
  56. package/lib/utils/index.ts +20 -4
  57. package/lib/utils/map-context-diff.test.ts +240 -10
  58. package/lib/utils/map-context-diff.ts +23 -14
  59. package/lib/utils/map-context-layer.test.ts +357 -0
  60. package/lib/utils/map-context-layer.ts +66 -0
  61. package/lib/utils/map-context.test.ts +136 -272
  62. package/lib/utils/map-context.ts +108 -39
  63. package/lib/utils/style.ts +71 -0
  64. package/lib/utils/url.test.ts +1 -1
  65. package/lib/utils/view.test.ts +146 -0
  66. package/lib/utils/view.ts +163 -0
  67. package/package.json +20 -3
@@ -0,0 +1,113 @@
1
+ import { EndpointError } from "@camptocamp/ogc-client";
2
+ import { Feature } from "geojson";
3
+ import BaseEvent from "ol/events/Event.js";
4
+ import type { Extent } from "ol/extent.js";
5
+ import {
6
+ ResolvedMapLayerState,
7
+ ResolvedMapState,
8
+ ResolvedMapViewState,
9
+ } from "./resolved-map-state.js";
10
+
11
+ export type FeaturesByLayerIndex = Map<number, Feature[]>;
12
+
13
+ export const FeaturesClickEventType = "features-click";
14
+ export interface FeaturesClickEvent {
15
+ type: typeof FeaturesClickEventType;
16
+ features: Feature[];
17
+ featuresByLayer: FeaturesByLayerIndex;
18
+ }
19
+
20
+ export const FeaturesHoverEventType = "features-hover";
21
+ export interface FeaturesHoverEvent {
22
+ type: typeof FeaturesHoverEventType;
23
+ features: Feature[];
24
+ featuresByLayer: FeaturesByLayerIndex;
25
+ }
26
+
27
+ export const MapClickEventType = "map-click";
28
+ export interface MapClickEvent {
29
+ type: typeof MapClickEventType;
30
+ coordinate: [number, number]; // expressed in lon/lat
31
+ }
32
+
33
+ export const MapViewStateChangeEventType = "map-view-state-change";
34
+ export interface MapViewStateChangeEvent {
35
+ type: typeof MapViewStateChangeEventType;
36
+ viewState: ResolvedMapViewState;
37
+ }
38
+
39
+ export const MapLayerStateChangeEventType = "map-layer-state-change";
40
+ export interface MapLayerStateChangeEvent {
41
+ type: typeof MapLayerStateChangeEventType;
42
+ layerState: ResolvedMapLayerState;
43
+ layerIndex: number;
44
+ layerId?: string | number;
45
+ }
46
+
47
+ export const MapStateChangeEventType = "map-state-change";
48
+ export interface MapStateChangeEvent {
49
+ type: typeof MapStateChangeEventType;
50
+ mapState: ResolvedMapState;
51
+ }
52
+
53
+ export const LayerCreationErrorEventType = "layer-creation-error";
54
+ export interface LayerCreationErrorEvent {
55
+ type: typeof LayerCreationErrorEventType;
56
+ error: Error;
57
+ }
58
+
59
+ export const LayerLoadingErrorEventType = "layer-loading-error";
60
+ export interface LayerLoadingErrorEvent {
61
+ type: typeof LayerLoadingErrorEventType;
62
+ error: Error;
63
+ httpStatus?: number;
64
+ }
65
+
66
+ /**
67
+ * DEPRECATED
68
+ * Use the MapViewStateChangeEvent instead
69
+ */
70
+ export const MapExtentChangeEventType = "map-extent-change";
71
+ export interface MapExtentChangeEvent {
72
+ type: typeof MapExtentChangeEventType;
73
+ extent: Extent;
74
+ }
75
+
76
+ /**
77
+ * DEPRECATED
78
+ * Use the MapLayerStateChangeEvent and LayerLoadingErrorEvent instead
79
+ */
80
+ export const SourceLoadErrorType = "source-load-error";
81
+ export class SourceLoadErrorEvent extends BaseEvent {
82
+ message: string;
83
+ httpStatus?: number;
84
+ constructor(error: EndpointError | Error | Response) {
85
+ super(SourceLoadErrorType);
86
+ if (error instanceof Response) {
87
+ this.message = error.statusText;
88
+ this.httpStatus = error.status;
89
+ } else if (error instanceof EndpointError) {
90
+ const e = error as EndpointError;
91
+ this.message = e.message;
92
+ this.httpStatus = e.httpStatus;
93
+ } else {
94
+ this.message = error.message;
95
+ }
96
+ }
97
+ }
98
+
99
+ export interface MapEventsByType {
100
+ [FeaturesClickEventType]: FeaturesClickEvent;
101
+ [FeaturesHoverEventType]: FeaturesHoverEvent;
102
+ [MapClickEventType]: MapClickEvent;
103
+ [MapViewStateChangeEventType]: MapViewStateChangeEvent;
104
+ [MapLayerStateChangeEventType]: MapLayerStateChangeEvent;
105
+ [MapStateChangeEventType]: MapStateChangeEvent;
106
+ [LayerCreationErrorEventType]: LayerCreationErrorEvent;
107
+ [LayerLoadingErrorEventType]: LayerLoadingErrorEvent;
108
+ /**
109
+ * DEPRECATED
110
+ */
111
+ [MapExtentChangeEventType]: MapExtentChangeEvent;
112
+ [SourceLoadErrorType]: SourceLoadErrorEvent;
113
+ }
@@ -1,2 +1,10 @@
1
- export * from "./map-context";
2
- export * from "./map-context-diff";
1
+ /**
2
+ * @group Types
3
+ * @packageDocumentation
4
+ */
5
+
6
+ export * from "./map-context.js";
7
+ export * from "./map-context-diff.js";
8
+ export * from "./events.js";
9
+ export * from "./resolved-map-state.js";
10
+ export * from "./style.js";
@@ -1,4 +1,4 @@
1
- import { MapContextLayer, MapContextView } from "./map-context";
1
+ import { MapContextLayer, MapContextView } from "./map-context.js";
2
2
 
3
3
  /**
4
4
  * Associates a position to a layer; the position is the index of
@@ -18,6 +18,15 @@ export interface MapContextLayerReordered {
18
18
  previousPosition: number;
19
19
  }
20
20
 
21
+ /**
22
+ * Describes a layer that was changed: both states before and after change are included
23
+ */
24
+ export interface MapContextLayerChanged {
25
+ layer: MapContextLayer;
26
+ previousLayer: MapContextLayer;
27
+ position: number;
28
+ }
29
+
21
30
  /**
22
31
  * Describes a delta between two contexts, in order to be
23
32
  * applied to an existing map.
@@ -29,9 +38,9 @@ export interface MapContextLayerReordered {
29
38
  * 4. change layers
30
39
  */
31
40
  export interface MapContextDiff {
32
- layersChanged: MapContextLayerPositioned[];
41
+ layersChanged: MapContextLayerChanged[];
33
42
  layersReordered: MapContextLayerReordered[];
34
43
  layersRemoved: MapContextLayerPositioned[];
35
44
  layersAdded: MapContextLayerPositioned[];
36
- viewChanges: MapContextView;
45
+ viewChanges?: MapContextView | null; // this is both optional (meaning no view change) and nullable (meaning reset to default view)
37
46
  }
@@ -1,11 +1,21 @@
1
1
  import { FeatureCollection, Geometry } from "geojson";
2
+ import { VectorStyle } from "./style.js";
3
+ import { WmsLayerDimensionValue } from "@camptocamp/ogc-client";
2
4
 
3
- export type LayerDimensions = Record<string, string>;
4
-
5
+ /**
6
+ * @private
7
+ * @inline
8
+ */
5
9
  export type LayerExtras = Record<string, unknown>;
6
10
 
7
11
  export interface MapContextBaseLayer {
12
+ /**
13
+ * An optional identifier for the layer; if provided, will improve performance when the layers is updated through a context diff.
14
+ */
8
15
  id?: string | number;
16
+ /**
17
+ * Optional version indicator; if provided, must be increased by the application for the change detection to trigger, otherwise the SDK will consider that the layer is unchanged.
18
+ */
9
19
  version?: number;
10
20
 
11
21
  /**
@@ -14,87 +24,270 @@ export interface MapContextBaseLayer {
14
24
  * non-serializable entities
15
25
  */
16
26
  extras?: LayerExtras;
27
+
28
+ /**
29
+ * Whether the layer is visible or not on the map. A non-visible layer will still have its data queried and kept in memory, so switching this on/off shows immediately on the map.
30
+ *
31
+ * Default value is `true` (visible).
32
+ */
17
33
  visibility?: boolean;
34
+
35
+ /**
36
+ * Opacity level; between 0 and 1.
37
+ *
38
+ * Default value is 1 (fully opaque).
39
+ */
18
40
  opacity?: number;
41
+
42
+ /**
43
+ * Optional label for the layer, typically used to represent the layer in a layer list or when showing a popup above a feature.
44
+ */
19
45
  label?: string;
46
+
47
+ /**
48
+ * Attributions for the layer. Optional but strongly recommended: remember to attribute your map!
49
+ */
20
50
  attributions?: string;
51
+
52
+ /**
53
+ * Whether data on the layer can be picked up using the `feature-click` event.
54
+ *
55
+ * Default value is `true`. Set to `false` to save performance.
56
+ */
57
+ clickable?: boolean;
58
+
59
+ /**
60
+ * Whether features on the layer can be picked up using the `feature-hover` event. Mostly has an effect only for vector layers.
61
+ *
62
+ * Default value is `false`.
63
+ */
64
+ hoverable?: boolean;
65
+
66
+ /**
67
+ * Controls the `Referer` header sent with tile/image requests.
68
+ * See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Request/referrerPolicy) for possible values.
69
+ *
70
+ * Support depends on the layer type and the map library used.
71
+ */
72
+ referrerPolicy?: ReferrerPolicy;
73
+ }
74
+
75
+ /**
76
+ * Dates are expressed as ISO8601 strings, e.g. "2023-01-01T00:00:00Z" or "2023-01-01"
77
+ */
78
+ export type DateString = string;
79
+
80
+ export interface TimeInterval {
81
+ begin: DateString;
82
+ end: DateString;
21
83
  }
84
+ export interface ValueInterval {
85
+ begin: WmsLayerDimensionValue;
86
+ end: WmsLayerDimensionValue;
87
+ }
88
+ export type LayerDimensionValue =
89
+ WmsLayerDimensionValue | WmsLayerDimensionValue[] | ValueInterval;
90
+
91
+ export type LayerTimeDimensionValue =
92
+ DateString | DateString[] | TimeInterval | "current";
22
93
 
23
94
  export interface MapContextLayerWms extends MapContextBaseLayer {
24
95
  type: "wms";
25
96
  url: string;
26
97
  name: string;
27
- dimensions?: LayerDimensions;
98
+
99
+ /**
100
+ * value of the built-in TIME dimension to request; can be a single date, a list of dates, a temporal interval, or a list of intervals
101
+ */
102
+ timeValue?: LayerTimeDimensionValue;
103
+
104
+ /**
105
+ * value of the built-in ELEVATION dimension to request; can be a single value, a list of discrete values, an interval, or a list of intervals
106
+ */
107
+ elevationValue?: LayerDimensionValue;
108
+
109
+ /**
110
+ * value of any other dimension to request (either scalar or temporal); key is the dimension name, it will be prefixed by DIM_ in the request
111
+ */
112
+ otherDimensionValues?: Record<
113
+ string,
114
+ LayerDimensionValue | LayerTimeDimensionValue
115
+ >;
116
+
117
+ /**
118
+ * If unspecified, will use the default one
119
+ */
28
120
  style?: string;
121
+
122
+ /**
123
+ * Vendor-specific WMS parameters that are appended as-is to every GetMap request.
124
+ * Use this for non-standard server extensions such as NcWMS (`COLORSCALERANGE`, `LOGSCALE`).
125
+ * Keys are case-sensitive; they are passed without transformation.
126
+ */
127
+ customParams?: Record<string, string>;
128
+
129
+ /**
130
+ * Whether to use tiled WMS requests. Tiled requests include a `TILED=true` parameter as per https://wiki.osgeo.org/wiki/WMS_Tiling_Client_Recommendation
131
+ *
132
+ * Using tiled requests allow tiles to be cached and thus the server load to potentially be reduced; on the other hand,
133
+ * it can increase the time to show the layer and degrade the quality of the rendering (e.g. with labels).
134
+ *
135
+ * Note: untiled requests are not supported by MapLibre-GL-JS
136
+ *
137
+ * Default value: `true` (use tiled requests)
138
+ */
139
+ useTiles?: boolean;
140
+
141
+ /**
142
+ * The image format MIME type to use for WMS requests, e.g. `"image/png"` or `"image/jpeg"`.
143
+ *
144
+ * If not specified, the WMS server's default format will be used.
145
+ */
146
+ format?: string;
147
+
148
+ /**
149
+ * An OGC encoded filter (e.g. an OGC `<Filter>` document) applied verbatim to the WMS
150
+ * GetMap `FILTER` parameter. Use it to restrict the features rendered by the layer.
151
+ *
152
+ * The value is passed through as-is; the SDK does not validate or transform it.
153
+ */
154
+ filter?: string;
29
155
  }
30
156
 
157
+ /**
158
+ * @private
159
+ * @inline
160
+ */
161
+ export type LayerDimensionSimpleValue =
162
+ string | number | DateString | "current";
163
+
31
164
  export interface MapContextLayerWmts extends MapContextBaseLayer {
32
165
  type: "wmts";
33
166
  url: string;
34
167
  name: string;
35
- dimensions?: LayerDimensions;
168
+ // TODO: add support for these
169
+ dimensionValues?: Record<string, LayerDimensionSimpleValue>;
36
170
  style?: string;
37
171
  }
38
172
 
39
- export interface MapContextLayerWfs extends MapContextBaseLayer {
40
- type: "wfs";
173
+ export interface MapContextLayerVector {
174
+ style?: VectorStyle;
175
+ hoverStyle?: VectorStyle;
176
+ }
177
+
178
+ export type MapContextLayerWfs = MapContextBaseLayer &
179
+ MapContextLayerVector & {
180
+ type: "wfs";
181
+ url: string;
182
+ featureType: string;
183
+ };
184
+
185
+ export type MapContextLayerOgcApi = MapContextBaseLayer &
186
+ MapContextLayerVector & {
187
+ type: "ogcapi";
188
+ url: string;
189
+ collection: string;
190
+ useTiles?: "vector" | "map";
191
+ tileMatrixSet?: string;
192
+ options?: Record<string, string>;
193
+ };
194
+
195
+ // Layer pointing to a MapLibre Style spec, see https://maplibre.org/maplibre-style-spec/
196
+ export interface MapContextLayerMapLibreStyle extends MapContextBaseLayer {
197
+ type: "maplibre-style";
198
+ styleUrl: string;
199
+ accessToken?: string;
200
+ }
201
+
202
+ export interface MapContextLayerGeotiff extends MapContextBaseLayer {
203
+ type: "geotiff";
41
204
  url: string;
42
- featureType: string;
43
205
  }
44
206
 
45
207
  export interface MapContextLayerXyz extends MapContextBaseLayer {
46
208
  type: "xyz";
47
209
  url: string;
210
+ tileFormat?: "application/vnd.mapbox-vector-tile"; // If not specified, the system will automatically assume tiles are images.
48
211
  }
49
212
 
50
- interface LayerGeojson extends MapContextBaseLayer {
51
- type: "geojson";
52
- }
53
- interface LayerGeojsonWithUrl extends LayerGeojson {
213
+ export type LayerGeojson = MapContextBaseLayer &
214
+ MapContextLayerVector & {
215
+ type: "geojson";
216
+ };
217
+ export interface LayerGeojsonWithUrl extends LayerGeojson {
54
218
  url: string;
55
219
  data?: never;
56
220
  }
57
- interface LayerGeojsonWithData extends LayerGeojson {
221
+ export interface LayerGeojsonWithData extends LayerGeojson {
58
222
  data: FeatureCollection<Geometry | null> | string;
59
223
  url?: never;
60
224
  }
61
-
62
- /**
63
- * @interface
64
- */
65
225
  export type MapContextLayerGeojson = LayerGeojsonWithUrl | LayerGeojsonWithData;
66
226
 
67
227
  /**
68
- * @interface
228
+ * A layer that can be used in a map context.
69
229
  */
70
230
  export type MapContextLayer =
71
231
  | MapContextLayerWms
72
232
  | MapContextLayerWmts
73
233
  | MapContextLayerWfs
74
234
  | MapContextLayerXyz
75
- | MapContextLayerGeojson;
235
+ | MapContextLayerGeojson
236
+ | MapContextLayerOgcApi
237
+ | MapContextLayerMapLibreStyle
238
+ | MapContextLayerGeotiff;
76
239
 
77
240
  export type Coordinate = [number, number];
78
241
 
79
242
  /**
80
- * Min X, min Y, max X, max Y
243
+ * Array components are respectively: minX, minY, maxX, maxY
81
244
  */
82
245
  export type Extent = [number, number, number, number];
83
246
 
84
247
  /**
85
248
  * @property center Expressed in longitude/latitude
249
+ * @property zoom
250
+ */
251
+ export interface ViewByZoomAndCenter {
252
+ center: Coordinate;
253
+ zoom: number;
254
+ }
255
+
256
+ /**
86
257
  * @property extent Expressed in longitude/latitude
87
- * @property maxExtent Expressed in longitude/latitude
88
258
  */
89
- export interface MapContextView {
90
- center?: Coordinate;
91
- zoom?: number;
92
- extent?: Extent;
259
+ export interface ViewByExtent {
260
+ extent: Extent;
261
+ }
262
+
263
+ /**
264
+ * @property geometry Expressed in GeoJSON
265
+ */
266
+ export interface ViewByGeometry {
267
+ geometry: Geometry;
268
+ }
269
+
270
+ /**
271
+ * A description of a map viewport in one of three ways:
272
+ * * by center and zoom level,
273
+ * * by extent,
274
+ * * by geometry (in GeoJSON)
275
+ *
276
+ * Also allows specifying constraints for zoom and extent.
277
+ */
278
+ export type MapContextView = (
279
+ ViewByZoomAndCenter | ViewByExtent | ViewByGeometry
280
+ ) & {
93
281
  maxZoom?: number;
94
282
  maxExtent?: Extent;
95
- }
283
+ };
96
284
 
285
+ /**
286
+ * A map context, containing layers and a view.
287
+ *
288
+ * Note: setting the `view` property to `null` indicates that the map should use a default global view.
289
+ */
97
290
  export interface MapContext {
98
291
  layers: MapContextLayer[];
99
- view: MapContextView;
292
+ view: MapContextView | null;
100
293
  }
@@ -0,0 +1,67 @@
1
+ import { Coordinate, Extent } from "./map-context.js";
2
+
3
+ export type MapLayerCreationStatus =
4
+ | {
5
+ created: true;
6
+ }
7
+ | {
8
+ creationError: true;
9
+ creationErrorMessage: string;
10
+ };
11
+
12
+ export type MapLayerLoadingStatus =
13
+ | {
14
+ loaded: true;
15
+ }
16
+ | {
17
+ loadingError: true;
18
+ loadingErrorMessage: string;
19
+ loadingErrorHttpStatus?: number;
20
+ }
21
+ | {
22
+ loading: true;
23
+ };
24
+
25
+ export interface MapLayerDataInfo {
26
+ featuresCount?: number;
27
+ geometryTypes?: Array<"Point" | "LineString" | "Polygon">;
28
+ }
29
+
30
+ export interface ResolvedMapLayerIdentity {
31
+ id?: string | number;
32
+ }
33
+
34
+ export type ResolvedMapLayerState = MapLayerCreationStatus &
35
+ MapLayerLoadingStatus &
36
+ MapLayerDataInfo &
37
+ ResolvedMapLayerIdentity;
38
+
39
+ /**
40
+ * Describes the actual view state of a map
41
+ */
42
+ export interface ResolvedMapViewState {
43
+ /** View center in longitude/latitude */
44
+ center: Coordinate;
45
+
46
+ /** Actual view extent in longitude/latitude */
47
+ extent: Extent;
48
+
49
+ /** Map units per pixel */
50
+ resolution: number;
51
+
52
+ /** Scale denominator (takes into account an estimated DPI) */
53
+ scaleDenominator: number;
54
+
55
+ /** Bearing in degrees; 90 is North (up) */
56
+ bearing: number;
57
+ }
58
+
59
+ /**
60
+ * Describes the actual state of a map after a context or context diff was applied to it.
61
+ * A `view` of null means the view state hasn't been changed yet.
62
+ * A `layer` item of null means the layer state hasn't been changed yet.
63
+ */
64
+ export interface ResolvedMapState {
65
+ layers: Array<ResolvedMapLayerState | null>;
66
+ view: ResolvedMapViewState | null;
67
+ }
@@ -0,0 +1,3 @@
1
+ import type { FlatStyleLike } from "ol/style/flat.js";
2
+
3
+ export type VectorStyle = FlatStyleLike;
@@ -1,4 +1,4 @@
1
- import { deepFreeze } from "./freeze";
1
+ import { deepFreeze } from "./freeze.js";
2
2
 
3
3
  describe("freeze util", () => {
4
4
  describe("deepFreeze", () => {