From 89d487e449908c645a5bf94540ef442996cbb652 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 13 Nov 2025 10:57:18 +0100 Subject: [PATCH] Picker Data Source: update getConfigValue with alias-based type safety (#20802) * Improve type safety in getConfigValue function * Refactor config typing in example document picker * Update index.ts * add unit tests --- .../example-document-picker-data-source.ts | 12 +++--- .../get-config-value.test.ts | 38 +++++++++++++++++++ .../core/utils/config-collection/index.ts | 16 ++++---- 3 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/get-config-value.test.ts diff --git a/src/Umbraco.Web.UI.Client/examples/picker-data-source/example-document-picker-data-source.ts b/src/Umbraco.Web.UI.Client/examples/picker-data-source/example-document-picker-data-source.ts index 47cfbdc043..3ba6c2d2ef 100644 --- a/src/Umbraco.Web.UI.Client/examples/picker-data-source/example-document-picker-data-source.ts +++ b/src/Umbraco.Web.UI.Client/examples/picker-data-source/example-document-picker-data-source.ts @@ -19,7 +19,9 @@ import type { UmbTreeChildrenOfRequestArgs, UmbTreeRootItemsRequestArgs, } from '@umbraco-cms/backoffice/tree'; -import { getConfigValue, type UmbConfigCollectionModel } from '@umbraco-cms/backoffice/utils'; +import { getConfigValue } from '@umbraco-cms/backoffice/utils'; + +type ExampleDocumentPickerConfigCollectionModel = Array<{ alias: 'filter'; value: string }>; export class ExampleDocumentPickerPropertyEditorDataSource extends UmbControllerBase @@ -30,17 +32,17 @@ export class ExampleDocumentPickerPropertyEditorDataSource #tree = new UmbDocumentTreeRepository(this); #item = new UmbDocumentItemRepository(this); #search = new UmbDocumentSearchRepository(this); - #config: UmbConfigCollectionModel = []; + #config: ExampleDocumentPickerConfigCollectionModel = []; treePickableFilter: (treeItem: UmbDocumentTreeItemModel) => boolean = (treeItem) => !!treeItem.unique; - setConfig(config: UmbConfigCollectionModel) { + setConfig(config: ExampleDocumentPickerConfigCollectionModel) { // TODO: add examples for all config options this.#config = config; this.#applyPickableFilterFromConfig(); } - getConfig(): UmbConfigCollectionModel { + getConfig(): ExampleDocumentPickerConfigCollectionModel { return this.#config; } @@ -72,7 +74,7 @@ export class ExampleDocumentPickerPropertyEditorDataSource } #getAllowedDocumentTypesConfig() { - const filterString = getConfigValue(this.#config, 'filter'); + const filterString = getConfigValue(this.#config, 'filter'); const filterArray = filterString ? filterString.split(',') : []; const allowedContentTypes: UmbDocumentSearchRequestArgs['allowedContentTypes'] = filterArray.map( (unique: string) => ({ diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/get-config-value.test.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/get-config-value.test.ts new file mode 100644 index 0000000000..9c510c09b3 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/get-config-value.test.ts @@ -0,0 +1,38 @@ +import { expect } from '@open-wc/testing'; +import { getConfigValue } from './index.js'; + +describe('getConfigValue', () => { + it('should return the value for a matching alias', () => { + const config = [ + { alias: 'foo', value: 123 }, + { alias: 'bar', value: 'hello' }, + ]; + const result = getConfigValue(config, 'foo'); + expect(result).to.equal(123); + }); + + it('should return undefined if alias is not found', () => { + const config = [ + { alias: 'foo', value: 123 }, + { alias: 'bar', value: 'hello' }, + ]; + const result = getConfigValue(config, 'baz'); + expect(result).to.be.undefined; + }); + + it('should return undefined if config is undefined', () => { + const result = getConfigValue(undefined, 'foo'); + expect(result).to.be.undefined; + }); + + it('should work with different value types', () => { + const config = [ + { alias: 'num', value: 42 }, + { alias: 'str', value: 'test' }, + { alias: 'obj', value: { a: 1 } }, + ]; + expect(getConfigValue(config, 'num')).to.equal(42); + expect(getConfigValue(config, 'str')).to.equal('test'); + expect(getConfigValue(config, 'obj')).to.deep.equal({ a: 1 }); + }); +}); diff --git a/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/index.ts b/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/index.ts index b4f03f1155..a2de3f4899 100644 --- a/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/index.ts +++ b/src/Umbraco.Web.UI.Client/src/packages/core/utils/config-collection/index.ts @@ -1,12 +1,14 @@ -import type { UmbConfigCollectionModel } from './types.js'; +import type { UmbConfigCollectionEntryModel } from './types.js'; /** * Get a value from a config collection by its alias. - * @param {UmbConfigCollectionModel | undefined} config - The config collection to get the value from. - * @param {string} alias - The alias of the value to get. - * @returns {T | undefined} The value with the specified alias, or undefined if not found or if the config is undefined. + * @param config - The config collection to get the value from. + * @param alias - The alias of the config entry to get the value for. + * @returns The value of the config entry with the specified alias, or undefined if not found. */ -export function getConfigValue(config: UmbConfigCollectionModel | undefined, alias: string): T | undefined { - const entry = config?.find((entry) => entry.alias === alias); - return entry?.value as T | undefined; +export function getConfigValue( + config: T[] | undefined, + alias: K, +) { + return config?.find((entry) => entry.alias === alias)?.value as Extract['value'] | undefined; }