@open-pioneer/ogc-features 1.3.0-dev.20260303160408 → 1.3.0-dev.20260310142705

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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @open-pioneer/ogc-features
2
2
 
3
- ## 1.3.0-dev.20260303160408
3
+ ## 1.3.0-dev.20260310142705
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -98,17 +98,12 @@
98
98
  ### Patch Changes
99
99
 
100
100
  - b152428: Update trails dependencies
101
- - Updated dependencies [b152428]
102
- - @open-pioneer/search@0.4.4
103
101
 
104
102
  ## 0.4.3
105
103
 
106
104
  ### Patch Changes
107
105
 
108
106
  - 28e092a: Update dependencies
109
- - Updated dependencies [7f5e58a]
110
- - Updated dependencies [28e092a]
111
- - @open-pioneer/search@0.4.3
112
107
 
113
108
  ## 0.4.2
114
109
 
@@ -119,11 +114,6 @@
119
114
  - 6977f0b: Added `strategy` and `rewriteUrl` options to the vector source factory.
120
115
  - 81bc7da: Update trails dependencies
121
116
  - 2c092dc: Update dependencies
122
- - Updated dependencies [4140646]
123
- - Updated dependencies [4140646]
124
- - Updated dependencies [81bc7da]
125
- - Updated dependencies [2c092dc]
126
- - @open-pioneer/search@0.4.2
127
117
 
128
118
  ## 0.4.1
129
119
 
@@ -141,51 +131,26 @@
141
131
 
142
132
  - 1a8ad89: Update package.json metadata
143
133
  - 6162979: Update versions of core packages
144
- - Updated dependencies [1a8ad89]
145
- - Updated dependencies [a0d8882]
146
- - Updated dependencies [6162979]
147
- - Updated dependencies [9334e81]
148
- - @open-pioneer/search@0.4.0
149
134
 
150
135
  ## 0.3.1
151
136
 
152
- ### Patch Changes
153
-
154
- - Updated dependencies [611ddb9]
155
- - @open-pioneer/search@0.3.1
156
-
157
137
  ## 0.3.0
158
138
 
159
139
  ### Minor Changes
160
140
 
161
141
  - ee7c2d4: Update runtime version.
162
142
 
163
- ### Patch Changes
164
-
165
- - Updated dependencies [0883bbd]
166
- - Updated dependencies [ee7c2d4]
167
- - Updated dependencies [0456500]
168
- - @open-pioneer/search@0.3.0
169
-
170
143
  ## 0.2.0
171
144
 
172
145
  ### Minor Changes
173
146
 
174
147
  - 70349a8: Update to new core packages major versions
175
148
 
176
- ### Patch Changes
177
-
178
- - Updated dependencies [70349a8]
179
- - @open-pioneer/search@0.2.0
180
-
181
149
  ## 0.1.1
182
150
 
183
151
  ### Patch Changes
184
152
 
185
153
  - dfc0896: Add OGC API Features search source
186
- - Updated dependencies [6209d6c]
187
- - Updated dependencies [565bd8b]
188
- - @open-pioneer/search@0.1.0
189
154
 
190
155
  ## 0.1.0
191
156
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/ogc-features",
4
- "version": "1.3.0-dev.20260303160408",
4
+ "version": "1.3.0-dev.20260310142705",
5
5
  "description": "This package provides utilities to work with OGC API Features services.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -36,8 +36,12 @@ class OgcFeaturesVectorSource extends VectorSource {
36
36
  format,
37
37
  strategy: bbox,
38
38
  attributions: options.attributions,
39
- loader: (...args) => {
40
- this.#load(...args);
39
+ // NOTE: it is IMPORTANT that every individual parameter is named here.
40
+ // OpenLayers tests the length of the signature, `...args` to forward these parameters
41
+ // will _not_ work!
42
+ // See also https://github.com/openlayers/openlayers/blob/da23cb2025bec601439fdc69076cf34af7582cb9/src/ol/source/Vector.js#L1041-L1042
43
+ loader: (e, r, p, s, f) => {
44
+ this.#load(e, r, p, s, f);
41
45
  },
42
46
  ...options.additionalOptions
43
47
  });
@@ -104,7 +108,10 @@ class OgcFeaturesVectorSource extends VectorSource {
104
108
  try {
105
109
  metadata = await getCollectionMetadata(this.#collectionUrl, this.#httpService);
106
110
  } catch (e) {
107
- LOG.error(`Failed to retrieve collection metadata for collection '${this.#collectionUrl}'`, e);
111
+ LOG.error(
112
+ `Failed to retrieve collection metadata for collection '${this.#collectionUrl}'`,
113
+ e
114
+ );
108
115
  throwAbortError();
109
116
  }
110
117
  try {
@@ -127,7 +134,10 @@ class OgcFeaturesVectorSource extends VectorSource {
127
134
  try {
128
135
  supportsOffset = await supportsOffsetStrategy(this.#itemsUrl, this.#httpService);
129
136
  } catch (e) {
130
- LOG.error(`Failed to retrieve collection information for collection '${this.#collectionUrl}'`, e);
137
+ LOG.error(
138
+ `Failed to retrieve collection information for collection '${this.#collectionUrl}'`,
139
+ e
140
+ );
131
141
  throwAbortError();
132
142
  }
133
143
  const options = this.#options;
@@ -1 +1 @@
1
- {"version":3,"file":"OgcFeaturesVectorSource.js","sources":["OgcFeaturesVectorSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createAbortError, createLogger, isAbortError, throwAbortError } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { Extent } from \"ol/extent\";\nimport Feature from \"ol/Feature\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport { bbox } from \"ol/loadingstrategy\";\nimport { Projection } from \"ol/proj\";\nimport VectorSource from \"ol/source/Vector\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { OgcFeatureVectorSourceOptions } from \"../api\";\nimport { CollectionMetadata, findMatchingCrs, getCollectionMetadata } from \"./Metadata\";\nimport { NextStrategy } from \"./NextStrategy\";\nimport { OffsetStrategy, supportsOffsetStrategy } from \"./OffsetStrategy\";\nimport { createCollectionRequestUrl } from \"./requestUtils\";\n\nconst LOG = createLogger(sourceId);\n\nconst CRS_OGC_CRS84 = \"http://www.opengis.net/def/crs/OGC/1.3/CRS84\";\n\ntype SuccessCallback = (features: Feature[]) => void;\ntype FailureCallback = () => void;\n\nexport class OgcFeaturesVectorSource extends VectorSource {\n #featureFormat: GeoJSON;\n #httpService: HttpService;\n\n #options: OgcFeatureVectorSourceOptions;\n #itemsUrl: string;\n #collectionUrl: string;\n\n #metadataPromise: Promise<CollectionMetadata> | undefined;\n #loadingStrategyPromise: Promise<\"offset\" | \"next\"> | undefined;\n\n // Cancels pending feature load operations.\n #featuresAbortController: AbortController | undefined;\n\n // Maps a map CRS to the corresponding request CRS that should be used for requests to the OGC API Features service.\n #mapCrsToRequestCrs: Record<string, string> = {\n // Special case: When map is in EPSG:4326, which defines lat/long-order for coordinate values,\n // make sure features are requested in CRS84, which has long/lat-order.\n // Reason for this special case is that OpenLayers always expects coordinates to be in long/lat-order,\n // even when the CRS definition specifies lat/long-order (as is the case for EPSG:4326).\n // CRS84 is mandated to be supported by all OGC API Features services, so we can safely assume that the service will support it.\n [\"4326\"]: CRS_OGC_CRS84,\n [\"EPSG:4326\"]: CRS_OGC_CRS84\n };\n\n constructor(options: OgcFeatureVectorSourceOptions, httpService: HttpService) {\n const format = new GeoJSON();\n super({\n format,\n strategy: bbox,\n attributions: options.attributions,\n loader: (...args) => {\n this.#load(...args);\n },\n ...options.additionalOptions\n });\n this.#featureFormat = format;\n this.#httpService = httpService;\n this.#options = options;\n this.#collectionUrl = `${options.baseUrl.replace(/\\/+$/, \"\")}/collections/${options.collectionId}`;\n this.#itemsUrl = `${this.#collectionUrl}/items`;\n }\n\n async #load(\n extent: Extent,\n _resolution: number,\n projection: Projection,\n success: SuccessCallback | undefined,\n failure: FailureCallback | undefined\n ) {\n try {\n const features = await this.#loadImpl(extent, projection);\n success?.(features);\n this.changed(); // Always trigger changed event to unstuck loading state\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load features from ogc service\", e);\n }\n failure?.();\n\n // Always trigger changed event to unstuck loading state\n // See https://github.com/openlayers/openlayers/issues/17335\n this.changed();\n }\n }\n\n async #loadImpl(extent: Extent, projection: Projection): Promise<Feature[]> {\n const [collectionMetadata, strategy] = await Promise.all([\n this.#loadCollectionMetadata(),\n this.#getLoadingStrategy()\n ]);\n\n // An extent-change should cancel open requests for older extents, because otherwise,\n // old and expensive requests could block new requests for a new extent\n // => no features are drawn on the current map for a long time.\n //TODO: More context\n this.#featuresAbortController?.abort(createAbortError());\n const abortController = (this.#featuresAbortController = new AbortController());\n const requestCrs = this.#getRequestCrs(collectionMetadata, projection);\n const fullUrl = this.#getRequestUrl(extent, requestCrs);\n const sharedOptions = {\n fullUrl,\n featureFormat: this.#featureFormat,\n limit: this.#options.limit,\n httpService: this.#httpService,\n signal: abortController.signal,\n onFeaturesLoaded: (features: Feature[]) => {\n LOG.debug(`Adding ${features.length} features`);\n this.addFeatures(features);\n }\n };\n let strategyImpl;\n switch (strategy) {\n case \"next\": {\n strategyImpl = new NextStrategy(sharedOptions);\n break;\n }\n case \"offset\":\n strategyImpl = new OffsetStrategy({\n ...sharedOptions,\n concurrency: this.#options.maxConcurrentRequests\n });\n break;\n }\n\n const features = await strategyImpl.load();\n LOG.debug(\"Finished loading features for extent:\", extent);\n return features;\n }\n\n // Fetches collection metadata from the service (once).\n async #loadCollectionMetadata() {\n const run = async () => {\n let metadata;\n try {\n metadata = await getCollectionMetadata(this.#collectionUrl, this.#httpService);\n } catch (e) {\n LOG.error(`Failed to retrieve collection metadata for collection '${this.#collectionUrl}'`, e);\n throwAbortError(); // Report error up the stack but only log error once\n }\n\n try {\n if (this.getAttributions() == null && metadata.attribution) {\n this.setAttributions(metadata.attribution);\n }\n } catch (e) {\n LOG.error(\"Failed to apply attributions\", e);\n throwAbortError(); // Report error up the stack but only log error once\n }\n return metadata;\n };\n\n const promise = (this.#metadataPromise ??= run());\n return await promise;\n }\n\n // Runs feature detection on the service (once).\n async #getLoadingStrategy() {\n const run = async () => {\n let supportsOffset;\n try {\n supportsOffset = await supportsOffsetStrategy(this.#itemsUrl, this.#httpService);\n } catch (e) {\n LOG.error(`Failed to retrieve collection information for collection '${this.#collectionUrl}'`, e);\n throwAbortError(); // Report error up the stack but only log error once\n }\n\n const options = this.#options;\n let strategy = options?.strategy || (supportsOffset ? \"offset\" : \"next\");\n if (strategy === \"offset\" && !supportsOffset) {\n strategy = \"next\";\n }\n return strategy;\n };\n\n const promise = (this.#loadingStrategyPromise ??= run());\n return await promise;\n }\n\n // Computes the appropriate request crs for the current configuration.\n #getRequestCrs(collectionMetadata: CollectionMetadata | undefined, projection: Projection) {\n const mapCrs = projection.getCode();\n\n const requestCrs = this.#options.crs ?? this.#mapCrsToRequestCrs[mapCrs];\n if (requestCrs) {\n return requestCrs;\n }\n\n const matchingMapCrs = findMatchingCrs(mapCrs, collectionMetadata?.crs);\n if (matchingMapCrs) {\n this.#mapCrsToRequestCrs[mapCrs] = matchingMapCrs;\n return matchingMapCrs;\n } else {\n LOG.error(`Map CRS '${mapCrs}' not supported by collection '${this.#collectionUrl}'.`);\n throwAbortError();\n }\n }\n\n #getRequestUrl(extent: Extent, requestCrs: string) {\n let requestUrl = createCollectionRequestUrl(this.#itemsUrl, extent, requestCrs);\n const rewriteUrl = this.#options.rewriteUrl;\n if (rewriteUrl) {\n requestUrl = rewriteUrl(requestUrl) ?? requestUrl;\n }\n return requestUrl;\n }\n}\n"],"names":["features"],"mappings":"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"}
1
+ {"version":3,"file":"OgcFeaturesVectorSource.js","sources":["OgcFeaturesVectorSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createAbortError, createLogger, isAbortError, throwAbortError } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { Extent } from \"ol/extent\";\nimport Feature from \"ol/Feature\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport { bbox } from \"ol/loadingstrategy\";\nimport { Projection } from \"ol/proj\";\nimport VectorSource from \"ol/source/Vector\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { OgcFeatureVectorSourceOptions } from \"../api\";\nimport { CollectionMetadata, findMatchingCrs, getCollectionMetadata } from \"./Metadata\";\nimport { NextStrategy } from \"./NextStrategy\";\nimport { OffsetStrategy, supportsOffsetStrategy } from \"./OffsetStrategy\";\nimport { createCollectionRequestUrl } from \"./requestUtils\";\n\nconst LOG = createLogger(sourceId);\n\nconst CRS_OGC_CRS84 = \"http://www.opengis.net/def/crs/OGC/1.3/CRS84\";\n\ntype SuccessCallback = (features: Feature[]) => void;\ntype FailureCallback = () => void;\n\nexport class OgcFeaturesVectorSource extends VectorSource {\n #featureFormat: GeoJSON;\n #httpService: HttpService;\n\n #options: OgcFeatureVectorSourceOptions;\n #itemsUrl: string;\n #collectionUrl: string;\n\n #metadataPromise: Promise<CollectionMetadata> | undefined;\n #loadingStrategyPromise: Promise<\"offset\" | \"next\"> | undefined;\n\n // Cancels pending feature load operations.\n #featuresAbortController: AbortController | undefined;\n\n // Maps a map CRS to the corresponding request CRS that should be used for requests to the OGC API Features service.\n #mapCrsToRequestCrs: Record<string, string> = {\n // Special case: When map is in EPSG:4326, which defines lat/long-order for coordinate values,\n // make sure features are requested in CRS84, which has long/lat-order.\n // Reason for this special case is that OpenLayers always expects coordinates to be in long/lat-order,\n // even when the CRS definition specifies lat/long-order (as is the case for EPSG:4326).\n // CRS84 is mandated to be supported by all OGC API Features services, so we can safely assume that the service will support it.\n [\"4326\"]: CRS_OGC_CRS84,\n [\"EPSG:4326\"]: CRS_OGC_CRS84\n };\n\n constructor(options: OgcFeatureVectorSourceOptions, httpService: HttpService) {\n const format = new GeoJSON();\n super({\n format,\n strategy: bbox,\n attributions: options.attributions,\n\n // NOTE: it is IMPORTANT that every individual parameter is named here.\n // OpenLayers tests the length of the signature, `...args` to forward these parameters\n // will _not_ work!\n // See also https://github.com/openlayers/openlayers/blob/da23cb2025bec601439fdc69076cf34af7582cb9/src/ol/source/Vector.js#L1041-L1042\n loader: (e, r, p, s, f) => {\n this.#load(e, r, p, s, f);\n },\n ...options.additionalOptions\n });\n this.#featureFormat = format;\n this.#httpService = httpService;\n this.#options = options;\n this.#collectionUrl = `${options.baseUrl.replace(/\\/+$/, \"\")}/collections/${options.collectionId}`;\n this.#itemsUrl = `${this.#collectionUrl}/items`;\n }\n\n async #load(\n extent: Extent,\n _resolution: number,\n projection: Projection,\n success: SuccessCallback | undefined,\n failure: FailureCallback | undefined\n ) {\n try {\n const features = await this.#loadImpl(extent, projection);\n success?.(features);\n this.changed(); // Always trigger changed event to unstuck loading state\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load features from ogc service\", e);\n }\n failure?.();\n\n // Always trigger changed event to unstuck loading state\n // See https://github.com/openlayers/openlayers/issues/17335\n this.changed();\n }\n }\n\n async #loadImpl(extent: Extent, projection: Projection): Promise<Feature[]> {\n const [collectionMetadata, strategy] = await Promise.all([\n this.#loadCollectionMetadata(),\n this.#getLoadingStrategy()\n ]);\n\n // An extent-change should cancel open requests for older extents, because otherwise,\n // old and expensive requests could block new requests for a new extent\n // => no features are drawn on the current map for a long time.\n //TODO: More context\n this.#featuresAbortController?.abort(createAbortError());\n const abortController = (this.#featuresAbortController = new AbortController());\n const requestCrs = this.#getRequestCrs(collectionMetadata, projection);\n const fullUrl = this.#getRequestUrl(extent, requestCrs);\n const sharedOptions = {\n fullUrl,\n featureFormat: this.#featureFormat,\n limit: this.#options.limit,\n httpService: this.#httpService,\n signal: abortController.signal,\n onFeaturesLoaded: (features: Feature[]) => {\n LOG.debug(`Adding ${features.length} features`);\n this.addFeatures(features);\n }\n };\n let strategyImpl;\n switch (strategy) {\n case \"next\": {\n strategyImpl = new NextStrategy(sharedOptions);\n break;\n }\n case \"offset\":\n strategyImpl = new OffsetStrategy({\n ...sharedOptions,\n concurrency: this.#options.maxConcurrentRequests\n });\n break;\n }\n\n const features = await strategyImpl.load();\n LOG.debug(\"Finished loading features for extent:\", extent);\n return features;\n }\n\n // Fetches collection metadata from the service (once).\n async #loadCollectionMetadata() {\n const run = async () => {\n let metadata;\n try {\n metadata = await getCollectionMetadata(this.#collectionUrl, this.#httpService);\n } catch (e) {\n LOG.error(\n `Failed to retrieve collection metadata for collection '${this.#collectionUrl}'`,\n e\n );\n throwAbortError(); // Report error up the stack but only log error once\n }\n\n try {\n if (this.getAttributions() == null && metadata.attribution) {\n this.setAttributions(metadata.attribution);\n }\n } catch (e) {\n LOG.error(\"Failed to apply attributions\", e);\n throwAbortError(); // Report error up the stack but only log error once\n }\n return metadata;\n };\n\n const promise = (this.#metadataPromise ??= run());\n return await promise;\n }\n\n // Runs feature detection on the service (once).\n async #getLoadingStrategy() {\n const run = async () => {\n let supportsOffset;\n try {\n supportsOffset = await supportsOffsetStrategy(this.#itemsUrl, this.#httpService);\n } catch (e) {\n LOG.error(\n `Failed to retrieve collection information for collection '${this.#collectionUrl}'`,\n e\n );\n throwAbortError(); // Report error up the stack but only log error once\n }\n\n const options = this.#options;\n let strategy = options?.strategy || (supportsOffset ? \"offset\" : \"next\");\n if (strategy === \"offset\" && !supportsOffset) {\n strategy = \"next\";\n }\n return strategy;\n };\n\n const promise = (this.#loadingStrategyPromise ??= run());\n return await promise;\n }\n\n // Computes the appropriate request crs for the current configuration.\n #getRequestCrs(collectionMetadata: CollectionMetadata | undefined, projection: Projection) {\n const mapCrs = projection.getCode();\n\n const requestCrs = this.#options.crs ?? this.#mapCrsToRequestCrs[mapCrs];\n if (requestCrs) {\n return requestCrs;\n }\n\n const matchingMapCrs = findMatchingCrs(mapCrs, collectionMetadata?.crs);\n if (matchingMapCrs) {\n this.#mapCrsToRequestCrs[mapCrs] = matchingMapCrs;\n return matchingMapCrs;\n } else {\n LOG.error(`Map CRS '${mapCrs}' not supported by collection '${this.#collectionUrl}'.`);\n throwAbortError();\n }\n }\n\n #getRequestUrl(extent: Extent, requestCrs: string) {\n let requestUrl = createCollectionRequestUrl(this.#itemsUrl, extent, requestCrs);\n const rewriteUrl = this.#options.rewriteUrl;\n if (rewriteUrl) {\n requestUrl = rewriteUrl(requestUrl) ?? requestUrl;\n }\n return requestUrl;\n }\n}\n"],"names":["features"],"mappings":"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"}