@open-pioneer/ogc-features 1.2.0-dev.20260121105545 → 1.3.0-dev-map-loading.20260202141334

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,9 +1,12 @@
1
1
  # @open-pioneer/ogc-features
2
2
 
3
- ## 1.2.0-dev.20260121105545
3
+ ## 1.3.0-dev-map-loading.20260202141334
4
+
5
+ ## 1.2.0
4
6
 
5
7
  ### Patch Changes
6
8
 
9
+ - 9c29256: Update to core packages 4.4.0
7
10
  - 279ca67: Use `workspace:*` instead of `workspace:^` for local package references as default. This ensures that trails packages from this repository are always referenced with their exact version to avoid potential issues with version mismatches. If a project specifically wants to use other versions for some trails packages, a pnpm override can be used to force other versions.
8
11
  - 9580bb4: Update various dependencies.
9
12
  - 9580bb4: Update to Chakra 3.31.0
@@ -0,0 +1,4 @@
1
+ const sourceId = "@open-pioneer/ogc-features/createVectorSource";
2
+
3
+ export { sourceId };
4
+ //# sourceMappingURL=source-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source-info.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,10 +1,10 @@
1
+ import { HttpService } from "@open-pioneer/http";
1
2
  import { FeatureLike } from "ol/Feature";
2
3
  import FeatureFormat from "ol/format/Feature";
3
4
  import VectorSource from "ol/source/Vector";
5
+ import { OgcFeatureVectorSourceOptions } from "./api";
4
6
  import { CollectionInfos, getCollectionInfos } from "./OffsetStrategy";
5
7
  import { FeatureResponse, queryFeatures } from "./requestUtils";
6
- import { OgcFeatureVectorSourceOptions } from "./api";
7
- import { HttpService } from "@open-pioneer/http";
8
8
  /**
9
9
  * This function creates an OpenLayers VectorSource for OGC API Features services to be used inside
10
10
  * an OpenLayers VectorLayer.
@@ -2,10 +2,11 @@ import { createLogger, isAbortError } from '@open-pioneer/core';
2
2
  import GeoJSON from 'ol/format/GeoJSON.js';
3
3
  import { bbox } from 'ol/loadingstrategy.js';
4
4
  import VectorSource from 'ol/source/Vector.js';
5
+ import { sourceId } from './_virtual/source-info.js';
5
6
  import { getCollectionInfos, loadAllFeaturesWithOffset } from './OffsetStrategy.js';
6
7
  import { createCollectionRequestUrl, queryFeatures } from './requestUtils.js';
7
8
 
8
- const LOG = createLogger("ogc-features:OgcFeatureSourceFactory");
9
+ const LOG = createLogger(sourceId);
9
10
  const DEFAULT_LIMIT = 5e3;
10
11
  const DEFAULT_CONCURRENTY = 6;
11
12
  function createVectorSource(options, httpService) {
@@ -1 +1 @@
1
- {"version":3,"file":"createVectorSource.js","sources":["createVectorSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger, isAbortError } from \"@open-pioneer/core\";\nimport { FeatureLike } from \"ol/Feature\";\nimport { FeatureLoader } from \"ol/featureloader\";\nimport FeatureFormat from \"ol/format/Feature\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport { bbox } from \"ol/loadingstrategy\";\nimport VectorSource from \"ol/source/Vector\";\nimport { CollectionInfos, getCollectionInfos, loadAllFeaturesWithOffset } from \"./OffsetStrategy\";\nimport { FeatureResponse, createCollectionRequestUrl, queryFeatures } from \"./requestUtils\";\nimport { OgcFeatureVectorSourceOptions } from \"./api\";\nimport { HttpService } from \"@open-pioneer/http\";\n\nconst LOG = createLogger(\"ogc-features:OgcFeatureSourceFactory\");\nconst DEFAULT_LIMIT = 5000;\nconst DEFAULT_CONCURRENTY = 6;\n\n/**\n * This function creates an OpenLayers VectorSource for OGC API Features services to be used inside\n * an OpenLayers VectorLayer.\n *\n * @param options Options for the vector source.\n * @param httpService Reference to httpService for fetching the features from the service.\n */\nexport function createVectorSource(\n options: OgcFeatureVectorSourceOptions,\n httpService: HttpService\n): VectorSource {\n return _createVectorSource(options, { httpService });\n}\n\n/**\n * @internal\n * Exported for tests\n */\nexport interface InternalOptions {\n httpService: HttpService;\n queryFeaturesParam?: QueryFeaturesFunc | undefined;\n addFeaturesParam?: AddFeaturesFunc | undefined;\n getCollectionInfosParam?: GetCollectionInfosFunc | undefined;\n}\n\n/**\n * @internal\n * Creates the actual vector source.\n * Exported for testing.\n * Exposes `queryFeatures`, `addFeatures` and `getCollectionInfos` for easier testing.\n */\nexport function _createVectorSource(\n options: OgcFeatureVectorSourceOptions,\n internals: InternalOptions\n): VectorSource {\n const httpService = internals.httpService;\n const collectionItemsURL = `${options.baseUrl}/collections/${options.collectionId}/items?`;\n const vectorSrc = new VectorSource({\n format: new GeoJSON(),\n strategy: bbox,\n attributions: options.attributions,\n ...options.additionalOptions\n });\n\n const queryFeaturesFunc = internals.queryFeaturesParam ?? queryFeatures;\n const getCollectionInfosFunc = internals.getCollectionInfosParam ?? getCollectionInfos;\n const addFeaturesFunc =\n internals.addFeaturesParam ||\n function (features: FeatureLike[]) {\n LOG.debug(`Adding ${features.length} features`);\n\n // Type mismatch FeatureLike <--> Feature<Geometry>\n // MIGHT be incorrect! We will see.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n vectorSrc.addFeatures(features as any);\n };\n\n // Abort controller for the currently pending request(s).\n // Used to cancel outdated requests.\n let abortController: AbortController;\n let collectionInfosPromise: Promise<CollectionInfos | undefined> | undefined;\n\n const loaderFunction: FeatureLoader = async (\n extent,\n _,\n __,\n success,\n failure\n ): Promise<void> => {\n collectionInfosPromise ??= getCollectionInfosFunc(collectionItemsURL, httpService);\n let collectionInfos;\n try {\n collectionInfos = await collectionInfosPromise;\n } catch (e) {\n LOG.error(\"Failed to retrieve collection information\", e);\n failure?.();\n collectionInfosPromise = undefined;\n return;\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 abortController?.abort(\"Extent changed\");\n abortController = new AbortController();\n\n const fullURL = createCollectionRequestUrl(\n collectionItemsURL,\n extent,\n options.crs,\n options.rewriteUrl\n );\n\n let strategy =\n options?.strategy || (collectionInfos?.supportsOffsetStrategy ? \"offset\" : \"next\");\n\n if (strategy === \"offset\" && !collectionInfos?.supportsOffsetStrategy) {\n strategy = \"next\";\n }\n\n try {\n const features = await loadAllFeatures(strategy, {\n fullURL: fullURL.toString(),\n httpService: httpService,\n featureFormat: vectorSrc.getFormat(),\n queryFeatures: queryFeaturesFunc,\n addFeatures: addFeaturesFunc,\n limit: options.limit ?? DEFAULT_LIMIT,\n maxConcurrentRequests: options.maxConcurrentRequests ?? DEFAULT_CONCURRENTY,\n signal: abortController.signal,\n collectionInfos: collectionInfos\n });\n // Type mismatch FeatureLike <--> Feature<Geometry>\n // MIGHT be incorrect! We will see.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n success?.(features as any);\n LOG.debug(\"Finished loading features for extent:\", extent);\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load features\", e);\n } else {\n LOG.debug(\"Query-Feature-Request aborted\", e);\n vectorSrc.removeLoadedExtent(extent);\n failure?.();\n }\n }\n };\n vectorSrc.setLoader(loaderFunction);\n return vectorSrc;\n}\n\n/** @internal **/\ntype QueryFeaturesFunc = typeof queryFeatures;\n/** @internal **/\ntype GetCollectionInfosFunc = typeof getCollectionInfos;\n/** @internal **/\ntype AddFeaturesFunc = (features: FeatureLike[]) => void;\n\n/** @internal **/\nexport interface LoadFeatureOptions {\n fullURL: string;\n httpService: HttpService;\n featureFormat: FeatureFormat | null;\n queryFeatures: QueryFeaturesFunc;\n addFeatures: AddFeaturesFunc;\n limit: number;\n maxConcurrentRequests: number;\n signal?: AbortSignal;\n collectionInfos?: CollectionInfos;\n}\n\n/**\n * @internal\n * Fetches _all_ features according to the given strategy.\n */\nfunction loadAllFeatures(\n strategy: \"next\" | \"offset\",\n options: LoadFeatureOptions\n): Promise<FeatureLike[]> {\n switch (strategy) {\n case \"next\":\n return loadAllFeaturesNextStrategy(options);\n case \"offset\":\n return loadAllFeaturesWithOffset(options);\n }\n}\n\n/**\n * @internal\n * Fetches features by following the `next` links in the server's response.\n */\nexport async function loadAllFeaturesNextStrategy(\n options: Omit<LoadFeatureOptions, \"offsetRequestProps\" | \"collectionInfos\">\n): Promise<FeatureLike[]> {\n const limit = options.limit;\n\n let url = new URL(options.fullURL);\n url.searchParams.set(\"limit\", limit.toString());\n let allFeatures: FeatureLike[] = [];\n do {\n const featureResp = await loadPages(\n [url.toString()],\n options.featureFormat,\n options.httpService,\n options.signal,\n options.addFeatures,\n options.queryFeatures\n );\n\n allFeatures = allFeatures.concat(featureResp.features);\n if (!featureResp.nextURL) {\n break;\n }\n\n url = new URL(featureResp.nextURL);\n // eslint-disable-next-line no-constant-condition\n } while (1);\n return allFeatures;\n}\n\nexport async function loadFeatures(\n requestUrl: string,\n featureFormat: FeatureFormat,\n httpService: HttpService,\n signal: AbortSignal | undefined,\n addFeaturesFunc: AddFeaturesFunc,\n queryFeaturesFunc: QueryFeaturesFunc = queryFeatures\n): Promise<FeatureResponse> {\n const featureResponse = await queryFeaturesFunc(requestUrl, featureFormat, httpService, signal);\n const features = featureResponse.features as FeatureLike[];\n addFeaturesFunc(features);\n return featureResponse;\n}\n\n/**\n * Loads features from multiple urls in parallel.\n * The URLs should represent pages of the same result set.\n * The `nextURL` of the last page (if any) is returned from this function.\n *\n * @internal\n */\nexport async function loadPages(\n allUrls: string[],\n featureFormat: FeatureFormat | null,\n httpService: HttpService,\n signal: AbortSignal | undefined,\n addFeaturesFunc: AddFeaturesFunc,\n queryFeaturesFunc: QueryFeaturesFunc = queryFeatures\n): Promise<FeatureResponse> {\n const allFeatureResponse: FeatureResponse = {\n nextURL: undefined,\n numberMatched: undefined,\n features: []\n };\n const allRequestPromises = allUrls.map(async (singleUrl, index): Promise<void> => {\n const isLast = index === allUrls.length - 1;\n\n const featureResponse = await queryFeaturesFunc(\n singleUrl,\n featureFormat,\n httpService,\n signal\n );\n addFeaturesFunc(featureResponse.features as FeatureLike[]);\n\n LOG.debug(\n `NextURL for index = ${index} (isLast = ${isLast}): ${\n featureResponse.nextURL || \"No Next URL\"\n }`\n );\n allFeatureResponse.features.push(...featureResponse.features);\n if (isLast) {\n allFeatureResponse.numberMatched = featureResponse.numberMatched;\n allFeatureResponse.nextURL = featureResponse.nextURL;\n }\n });\n await Promise.all(allRequestPromises);\n return allFeatureResponse;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"createVectorSource.js","sources":["createVectorSource.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2023-2025 Open Pioneer project (https://github.com/open-pioneer)\n// SPDX-License-Identifier: Apache-2.0\nimport { createLogger, isAbortError } from \"@open-pioneer/core\";\nimport { HttpService } from \"@open-pioneer/http\";\nimport { FeatureLike } from \"ol/Feature\";\nimport { FeatureLoader } from \"ol/featureloader\";\nimport FeatureFormat from \"ol/format/Feature\";\nimport GeoJSON from \"ol/format/GeoJSON\";\nimport { bbox } from \"ol/loadingstrategy\";\nimport VectorSource from \"ol/source/Vector\";\nimport { sourceId } from \"open-pioneer:source-info\";\nimport { OgcFeatureVectorSourceOptions } from \"./api\";\nimport { CollectionInfos, getCollectionInfos, loadAllFeaturesWithOffset } from \"./OffsetStrategy\";\nimport { FeatureResponse, createCollectionRequestUrl, queryFeatures } from \"./requestUtils\";\n\nconst LOG = createLogger(sourceId);\nconst DEFAULT_LIMIT = 5000;\nconst DEFAULT_CONCURRENTY = 6;\n\n/**\n * This function creates an OpenLayers VectorSource for OGC API Features services to be used inside\n * an OpenLayers VectorLayer.\n *\n * @param options Options for the vector source.\n * @param httpService Reference to httpService for fetching the features from the service.\n */\nexport function createVectorSource(\n options: OgcFeatureVectorSourceOptions,\n httpService: HttpService\n): VectorSource {\n return _createVectorSource(options, { httpService });\n}\n\n/**\n * @internal\n * Exported for tests\n */\nexport interface InternalOptions {\n httpService: HttpService;\n queryFeaturesParam?: QueryFeaturesFunc | undefined;\n addFeaturesParam?: AddFeaturesFunc | undefined;\n getCollectionInfosParam?: GetCollectionInfosFunc | undefined;\n}\n\n/**\n * @internal\n * Creates the actual vector source.\n * Exported for testing.\n * Exposes `queryFeatures`, `addFeatures` and `getCollectionInfos` for easier testing.\n */\nexport function _createVectorSource(\n options: OgcFeatureVectorSourceOptions,\n internals: InternalOptions\n): VectorSource {\n const httpService = internals.httpService;\n const collectionItemsURL = `${options.baseUrl}/collections/${options.collectionId}/items?`;\n const vectorSrc = new VectorSource({\n format: new GeoJSON(),\n strategy: bbox,\n attributions: options.attributions,\n ...options.additionalOptions\n });\n\n const queryFeaturesFunc = internals.queryFeaturesParam ?? queryFeatures;\n const getCollectionInfosFunc = internals.getCollectionInfosParam ?? getCollectionInfos;\n const addFeaturesFunc =\n internals.addFeaturesParam ||\n function (features: FeatureLike[]) {\n LOG.debug(`Adding ${features.length} features`);\n\n // Type mismatch FeatureLike <--> Feature<Geometry>\n // MIGHT be incorrect! We will see.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n vectorSrc.addFeatures(features as any);\n };\n\n // Abort controller for the currently pending request(s).\n // Used to cancel outdated requests.\n let abortController: AbortController;\n let collectionInfosPromise: Promise<CollectionInfos | undefined> | undefined;\n\n const loaderFunction: FeatureLoader = async (\n extent,\n _,\n __,\n success,\n failure\n ): Promise<void> => {\n collectionInfosPromise ??= getCollectionInfosFunc(collectionItemsURL, httpService);\n let collectionInfos;\n try {\n collectionInfos = await collectionInfosPromise;\n } catch (e) {\n LOG.error(\"Failed to retrieve collection information\", e);\n failure?.();\n collectionInfosPromise = undefined;\n return;\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 abortController?.abort(\"Extent changed\");\n abortController = new AbortController();\n\n const fullURL = createCollectionRequestUrl(\n collectionItemsURL,\n extent,\n options.crs,\n options.rewriteUrl\n );\n\n let strategy =\n options?.strategy || (collectionInfos?.supportsOffsetStrategy ? \"offset\" : \"next\");\n\n if (strategy === \"offset\" && !collectionInfos?.supportsOffsetStrategy) {\n strategy = \"next\";\n }\n\n try {\n const features = await loadAllFeatures(strategy, {\n fullURL: fullURL.toString(),\n httpService: httpService,\n featureFormat: vectorSrc.getFormat(),\n queryFeatures: queryFeaturesFunc,\n addFeatures: addFeaturesFunc,\n limit: options.limit ?? DEFAULT_LIMIT,\n maxConcurrentRequests: options.maxConcurrentRequests ?? DEFAULT_CONCURRENTY,\n signal: abortController.signal,\n collectionInfos: collectionInfos\n });\n // Type mismatch FeatureLike <--> Feature<Geometry>\n // MIGHT be incorrect! We will see.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n success?.(features as any);\n LOG.debug(\"Finished loading features for extent:\", extent);\n } catch (e) {\n if (!isAbortError(e)) {\n LOG.error(\"Failed to load features\", e);\n } else {\n LOG.debug(\"Query-Feature-Request aborted\", e);\n vectorSrc.removeLoadedExtent(extent);\n failure?.();\n }\n }\n };\n vectorSrc.setLoader(loaderFunction);\n return vectorSrc;\n}\n\n/** @internal **/\ntype QueryFeaturesFunc = typeof queryFeatures;\n/** @internal **/\ntype GetCollectionInfosFunc = typeof getCollectionInfos;\n/** @internal **/\ntype AddFeaturesFunc = (features: FeatureLike[]) => void;\n\n/** @internal **/\nexport interface LoadFeatureOptions {\n fullURL: string;\n httpService: HttpService;\n featureFormat: FeatureFormat | null;\n queryFeatures: QueryFeaturesFunc;\n addFeatures: AddFeaturesFunc;\n limit: number;\n maxConcurrentRequests: number;\n signal?: AbortSignal;\n collectionInfos?: CollectionInfos;\n}\n\n/**\n * @internal\n * Fetches _all_ features according to the given strategy.\n */\nfunction loadAllFeatures(\n strategy: \"next\" | \"offset\",\n options: LoadFeatureOptions\n): Promise<FeatureLike[]> {\n switch (strategy) {\n case \"next\":\n return loadAllFeaturesNextStrategy(options);\n case \"offset\":\n return loadAllFeaturesWithOffset(options);\n }\n}\n\n/**\n * @internal\n * Fetches features by following the `next` links in the server's response.\n */\nexport async function loadAllFeaturesNextStrategy(\n options: Omit<LoadFeatureOptions, \"offsetRequestProps\" | \"collectionInfos\">\n): Promise<FeatureLike[]> {\n const limit = options.limit;\n\n let url = new URL(options.fullURL);\n url.searchParams.set(\"limit\", limit.toString());\n let allFeatures: FeatureLike[] = [];\n do {\n const featureResp = await loadPages(\n [url.toString()],\n options.featureFormat,\n options.httpService,\n options.signal,\n options.addFeatures,\n options.queryFeatures\n );\n\n allFeatures = allFeatures.concat(featureResp.features);\n if (!featureResp.nextURL) {\n break;\n }\n\n url = new URL(featureResp.nextURL);\n // eslint-disable-next-line no-constant-condition\n } while (1);\n return allFeatures;\n}\n\nexport async function loadFeatures(\n requestUrl: string,\n featureFormat: FeatureFormat,\n httpService: HttpService,\n signal: AbortSignal | undefined,\n addFeaturesFunc: AddFeaturesFunc,\n queryFeaturesFunc: QueryFeaturesFunc = queryFeatures\n): Promise<FeatureResponse> {\n const featureResponse = await queryFeaturesFunc(requestUrl, featureFormat, httpService, signal);\n const features = featureResponse.features as FeatureLike[];\n addFeaturesFunc(features);\n return featureResponse;\n}\n\n/**\n * Loads features from multiple urls in parallel.\n * The URLs should represent pages of the same result set.\n * The `nextURL` of the last page (if any) is returned from this function.\n *\n * @internal\n */\nexport async function loadPages(\n allUrls: string[],\n featureFormat: FeatureFormat | null,\n httpService: HttpService,\n signal: AbortSignal | undefined,\n addFeaturesFunc: AddFeaturesFunc,\n queryFeaturesFunc: QueryFeaturesFunc = queryFeatures\n): Promise<FeatureResponse> {\n const allFeatureResponse: FeatureResponse = {\n nextURL: undefined,\n numberMatched: undefined,\n features: []\n };\n const allRequestPromises = allUrls.map(async (singleUrl, index): Promise<void> => {\n const isLast = index === allUrls.length - 1;\n\n const featureResponse = await queryFeaturesFunc(\n singleUrl,\n featureFormat,\n httpService,\n signal\n );\n addFeaturesFunc(featureResponse.features as FeatureLike[]);\n\n LOG.debug(\n `NextURL for index = ${index} (isLast = ${isLast}): ${\n featureResponse.nextURL || \"No Next URL\"\n }`\n );\n allFeatureResponse.features.push(...featureResponse.features);\n if (isLast) {\n allFeatureResponse.numberMatched = featureResponse.numberMatched;\n allFeatureResponse.nextURL = featureResponse.nextURL;\n }\n });\n await Promise.all(allRequestPromises);\n return allFeatureResponse;\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@open-pioneer/ogc-features",
4
- "version": "1.2.0-dev.20260121105545",
4
+ "version": "1.3.0-dev-map-loading.20260202141334",
5
5
  "description": "This package provides utilities to work with OGC API Features services.",
6
6
  "keywords": [
7
7
  "open-pioneer-trails"
@@ -14,8 +14,8 @@
14
14
  "directory": "src/packages/ogc-features"
15
15
  },
16
16
  "dependencies": {
17
- "@open-pioneer/core": "4.4.0-dev.20260121102820",
18
- "@open-pioneer/http": "4.4.0-dev.20260121102820",
17
+ "@open-pioneer/core": "^4.4.0",
18
+ "@open-pioneer/http": "^4.4.0",
19
19
  "ol": "^10.7.0",
20
20
  "uuid": "^13.0.0"
21
21
  },