From 285a2d2be729cf3f1eb2fb3f3418a0f86610173e Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Wed, 10 Jan 2024 20:49:25 +0100 Subject: [PATCH 1/7] Throw error if queryParameters is missing on dish search configuration --- packages/clients/dish/CHANGELOG.md | 4 ++++ packages/clients/dish/src/utils/navigateToDenkmal.ts | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/packages/clients/dish/CHANGELOG.md b/packages/clients/dish/CHANGELOG.md index 80e9a421f..94982ebed 100644 --- a/packages/clients/dish/CHANGELOG.md +++ b/packages/clients/dish/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## unpublished + +- Fix: The client now properly throws an error if `queryParameters` is missing on the `searchMethod` configuration of the `dish` search. + ## 1.1.0 - Feature: Update icon of `layerChooser` in `iconMenu` to `fa-layer-group` to clear-up the content hidden behind the menu button. diff --git a/packages/clients/dish/src/utils/navigateToDenkmal.ts b/packages/clients/dish/src/utils/navigateToDenkmal.ts index 352977060..dd98581b7 100644 --- a/packages/clients/dish/src/utils/navigateToDenkmal.ts +++ b/packages/clients/dish/src/utils/navigateToDenkmal.ts @@ -11,6 +11,11 @@ export function navigateToDenkmal(instance, objektId: string) { if (!wfsConfig) { throw new Error('Client is missing wfsConfig on DISH search method.') } + if (!wfsConfig.queryParameters) { + throw new Error( + 'Client is missing wfsConfig.queryParameters on DISH search method.' + ) + } getWfsFeatures(null, denkmaelerWfsService.url, objektId, { ...wfsConfig.queryParameters.wfsConfiguration, From 70162055a375e70523651b37c32751ac32372cff Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Thu, 11 Jan 2024 20:05:42 +0100 Subject: [PATCH 2/7] Change getWfsFeatures to throw errors on incomplete configuration Also, fix types to better reflect its usage. --- packages/lib/getFeatures/CHANGELOG.md | 4 +++ packages/lib/getFeatures/types.ts | 14 ++++++++ .../lib/getFeatures/wfs/buildWfsFilter.ts | 15 ++------ packages/lib/getFeatures/wfs/index.ts | 24 ++++++------- packages/lib/getFeatures/wfs/match.ts | 35 +++++++++++-------- 5 files changed, 51 insertions(+), 41 deletions(-) diff --git a/packages/lib/getFeatures/CHANGELOG.md b/packages/lib/getFeatures/CHANGELOG.md index 385b843bb..b218c442b 100644 --- a/packages/lib/getFeatures/CHANGELOG.md +++ b/packages/lib/getFeatures/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## unpublished + +- Breaking: `getWfsFeatures` now throws errors if required parameters on the wfs configuration are missing instead of only printing error messages on the console. + ## 1.0.0 Initial release. diff --git a/packages/lib/getFeatures/types.ts b/packages/lib/getFeatures/types.ts index 8c48c070b..a40bb4530 100644 --- a/packages/lib/getFeatures/types.ts +++ b/packages/lib/getFeatures/types.ts @@ -12,6 +12,20 @@ export interface AdditionalSearchOptions { typeNames?: string | string[] } +/* + * Explanation by dimension: + * First: each child resembles a query + * Second: children will be ANDed on multiple children + * Third: [key, value] where key is a property name + * Explanation by example: + * [[['a', 'b'], ['a', 'c']], [['a', 'b']]] + * becomes + * QUERY(a=b && c=d), QUERY(a=b) + * where the second query is only executed if the first doesn't fill + * maxFeatures to its limit. + */ +export type KeyValueSetArray = Array> + /** Adds the possibility to have a 'title' attribute in a GeoJSON Feature */ export interface PolarGeoJsonFeature extends GeoJsonFeature { /** The projection of the coordinates of the features */ diff --git a/packages/lib/getFeatures/wfs/buildWfsFilter.ts b/packages/lib/getFeatures/wfs/buildWfsFilter.ts index 97142a217..463a1161f 100644 --- a/packages/lib/getFeatures/wfs/buildWfsFilter.ts +++ b/packages/lib/getFeatures/wfs/buildWfsFilter.ts @@ -1,4 +1,4 @@ -import { WfsParameters } from '../types' +import { KeyValueSetArray, WfsParameters } from '../types' const removeLinebreaks = (s) => s.replace(/\r?\n|\r/g, '') @@ -58,21 +58,10 @@ const buildWfsFilterQuery = ( * Builds filter of multiple queries from possible interpretations of inputs. * Multiple queries are sent so that service may stop computing after * maxFeatures has been fulfilled. - * @param inputs - Explanation by dimension. - * First: each child resembles a query - * Second: children will be ANDed on multiple children - * Third: [key, value] where key is a property name - * Explanation by example. - * [[['a', 'b'], ['a', 'c']], [['a', 'b']]] - * becomes - * QUERY(a=b && c=d), QUERY(a=b) - * where the second query is only executed if the first doesn't fill - * maxFeatures to its limit. - * @param parameters - @see WfsParameters * @returns request xml */ export const buildWfsFilter = ( - inputs: Array>, + inputs: KeyValueSetArray, parameters: WfsParameters ) => removeLinebreaks( diff --git a/packages/lib/getFeatures/wfs/index.ts b/packages/lib/getFeatures/wfs/index.ts index 5f96c9b7b..3e7099274 100644 --- a/packages/lib/getFeatures/wfs/index.ts +++ b/packages/lib/getFeatures/wfs/index.ts @@ -1,4 +1,4 @@ -import { WfsParameters } from '../types' +import { KeyValueSetArray, WfsParameters } from '../types' import { errorCheck } from '../utils/errorCheck' import { parseWfsResponse } from './parse' import { buildWfsFilter } from './buildWfsFilter' @@ -11,24 +11,20 @@ export function getWfsFeatures( parameters: WfsParameters ) { const { fieldName, patterns, patternKeys } = parameters - // arrays OF sets OF key-value-pairs - let inputs: string[][][] = [[[]]] - - if (fieldName && patterns) { - console.error( - '@polar/lib-get-features: Using both fieldName and patterns for WFS search. These are mutually exclusive. Patterns will be ignored.' + if (!fieldName && (!patterns || !patternKeys)) { + throw new Error( + 'Incomplete WFS search configuration. Either "fieldName" or "patterns" and "patternKeys" are required.' ) } - - if (fieldName) { - inputs = [[[fieldName, inputValue]]] - } else if (patterns && patternKeys) { - inputs = match(patterns, patternKeys, inputValue) - } else { + if (fieldName && patterns) { console.error( - '@polar/lib-get-features: Incomplete WFS search configuration. Either "fieldName" or "patterns" and "patternKeys" are required.' + '@polar/lib-get-features: Using both fieldName and patterns for WFS search. These are mutually exclusive. Patterns will be ignored.' ) } + // arrays of sets of key-value-pairs + const inputs: KeyValueSetArray = fieldName + ? [[[fieldName, inputValue]]] + : match(patterns, patternKeys, inputValue) const body = buildWfsFilter(inputs, parameters) diff --git a/packages/lib/getFeatures/wfs/match.ts b/packages/lib/getFeatures/wfs/match.ts index db7b44fcd..1ffb2c79c 100644 --- a/packages/lib/getFeatures/wfs/match.ts +++ b/packages/lib/getFeatures/wfs/match.ts @@ -1,6 +1,8 @@ // code doesn't produce RegExpMatchArray where index is not set ... :| /* eslint-disable @typescript-eslint/no-non-null-assertion */ +import { KeyValueSetArray } from '../types' + export type Separator = string export type Slot = RegExpMatchArray export type Block = Slot | Separator @@ -55,10 +57,10 @@ const sortComparableMatches = (comparableA, comparableB) => { * 2. pattern fulfillment */ const sortMatches = ( - matches: string[][][], + matches: KeyValueSetArray, patterns: string[], uninterpretedCharacters: number[] -): string[][][] => { +): KeyValueSetArray => { const comparableMatches = matches.map((match, index) => ({ match, uninterpreted: uninterpretedCharacters[index], @@ -72,7 +74,7 @@ const sortMatches = ( // remove duplicates and empty matches const known: string[] = [] - const sortedFilteredMatches = sortedMatches.filter((match) => { + return sortedMatches.filter((match) => { if (match.length === 0) { return false } @@ -83,23 +85,31 @@ const sortMatches = ( known.push(asString) return true }) - - return sortedFilteredMatches } /** * matches an input string to patterns */ export const match = ( - patterns: string[], - patternKeys: Record, + patterns: string[] | undefined, + patternKeys: Record | undefined, inputValue: string -): string[][][] => { - const matches: string[][][] = [] +): KeyValueSetArray => { + if (!patterns) { + throw new Error( + '@polar/lib-get-features: Parameter "patterns" is missing on wfs configuration for pattern-based search.' + ) + } + if (!patternKeys) { + throw new Error( + '@polar/lib-get-features: Parameter "patternKeys" is missing on wfs configuration for pattern-based search.' + ) + } + const matches: KeyValueSetArray = [] const uninterpretedCharacters: number[] = [] patterns.forEach((pattern) => { const patternBlocks = getBlocks(pattern) - const patternMapping: string[][] = [] + const patternMapping: Array<[string, string]> = [] let traverseInput = inputValue patternBlocks.forEach((block) => { @@ -126,8 +136,5 @@ export const match = ( uninterpretedCharacters.push(traverseInput.length) matches.push(patternMapping) }) - - const sortedMatches = sortMatches(matches, patterns, uninterpretedCharacters) - - return sortedMatches + return sortMatches(matches, patterns, uninterpretedCharacters) } From 7311ce95cdc09961b3f7a6c9b254307d2c9524f6 Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Thu, 11 Jan 2024 20:06:31 +0100 Subject: [PATCH 3/7] Convert getWfsFeatures to an async/await function --- packages/lib/getFeatures/wfs/index.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/packages/lib/getFeatures/wfs/index.ts b/packages/lib/getFeatures/wfs/index.ts index 3e7099274..82b228f66 100644 --- a/packages/lib/getFeatures/wfs/index.ts +++ b/packages/lib/getFeatures/wfs/index.ts @@ -4,7 +4,7 @@ import { parseWfsResponse } from './parse' import { buildWfsFilter } from './buildWfsFilter' import { match } from './match' -export function getWfsFeatures( +export async function getWfsFeatures( signal: AbortSignal | null, url: string, inputValue: string, @@ -28,10 +28,7 @@ export function getWfsFeatures( const body = buildWfsFilter(inputs, parameters) - return fetch(encodeURI(url), { signal, method: 'POST', body }).then( - (response: Response) => { - errorCheck(response) - return parseWfsResponse(response, fieldName || patterns, !fieldName) - } - ) + const response = await fetch(encodeURI(url), { signal, method: 'POST', body }) + errorCheck(response) + return parseWfsResponse(response, fieldName || patterns, !fieldName) } From 19e1d7536a597be176ee4121c57a7af5dea9de55 Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Mon, 19 Feb 2024 12:19:08 +0100 Subject: [PATCH 4/7] Remove unused ts-expect-error --- packages/lib/getFeatures/gazetteer/parse.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/lib/getFeatures/gazetteer/parse.ts b/packages/lib/getFeatures/gazetteer/parse.ts index f91262dd4..05011e428 100644 --- a/packages/lib/getFeatures/gazetteer/parse.ts +++ b/packages/lib/getFeatures/gazetteer/parse.ts @@ -24,7 +24,6 @@ export function parseGazetteerResponse( const gmlFeatures = new DOMParser() .parseFromString(text, 'application/xml') .getElementsByTagName(`wfs:${memberSuffix}`) - // @ts-expect-error | This is needed as this already is a workaround because the GeoJSON reader can't read the XMLResponse from a WFS-G const featureCollection: FeatureCollection = { type: 'FeatureCollection', features, From d3cc2cc20a15466d71937a8ffed0f60890844c91 Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Mon, 19 Feb 2024 12:19:40 +0100 Subject: [PATCH 5/7] Move type assertion to correct place --- packages/lib/getFeatures/wfs/getFeatureTitleFromPattern.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib/getFeatures/wfs/getFeatureTitleFromPattern.ts b/packages/lib/getFeatures/wfs/getFeatureTitleFromPattern.ts index 9d4b2ba18..7071a5f58 100644 --- a/packages/lib/getFeatures/wfs/getFeatureTitleFromPattern.ts +++ b/packages/lib/getFeatures/wfs/getFeatureTitleFromPattern.ts @@ -28,8 +28,8 @@ export const getFeatureTitleFromPattern = ( const keys = blocks.reduce( (keyAccumulator, block) => Array.isArray(block) ? [...keyAccumulator, block[1]] : keyAccumulator, - [] - ) as string[] + [] as string[] + ) const foundKeys = keys.reduce( (sum, key) => typeof properties[key] !== 'undefined' && properties[key] !== '' From 42ca46f91feb10a38d547dc39f2a773e45824b8e Mon Sep 17 00:00:00 2001 From: Pascal Roehling Date: Fri, 23 Feb 2024 14:09:41 +0100 Subject: [PATCH 6/7] Remove redundant changelog entry --- packages/clients/dish/CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/clients/dish/CHANGELOG.md b/packages/clients/dish/CHANGELOG.md index ebf1c24fb..66a27e533 100644 --- a/packages/clients/dish/CHANGELOG.md +++ b/packages/clients/dish/CHANGELOG.md @@ -1,9 +1,5 @@ # CHANGELOG -## unpublished - -- Fix: The client now properly throws an error if `queryParameters` is missing on the `searchMethod` configuration of the `dish` search. - ## 1.1.1 - Fix: The marker previously disappeared on being moved/reclicked on a second feature. This issue has been resolved. From 1b0779db302bdc6dd74aa6a1c8d945a8c2b926a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pascal=20R=C3=B6hling?= <73653210+dopenguin@users.noreply.github.com> Date: Wed, 28 Feb 2024 08:08:35 +0100 Subject: [PATCH 7/7] Deduplicate types Co-authored-by: Dennis Sen <108349707+warm-coolguy@users.noreply.github.com> --- packages/lib/getFeatures/wfs/match.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib/getFeatures/wfs/match.ts b/packages/lib/getFeatures/wfs/match.ts index 1ffb2c79c..bf71ad9ca 100644 --- a/packages/lib/getFeatures/wfs/match.ts +++ b/packages/lib/getFeatures/wfs/match.ts @@ -109,7 +109,7 @@ export const match = ( const uninterpretedCharacters: number[] = [] patterns.forEach((pattern) => { const patternBlocks = getBlocks(pattern) - const patternMapping: Array<[string, string]> = [] + const patternMapping: KeyValueSetArray[number] = [] let traverseInput = inputValue patternBlocks.forEach((block) => {