diff --git a/packages/config-loader/src/index.ts b/packages/config-loader/src/index.ts index b08380d8ce..9ad54c5f18 100644 --- a/packages/config-loader/src/index.ts +++ b/packages/config-loader/src/index.ts @@ -15,6 +15,6 @@ */ export { readEnvConfig, loadConfigSchema } from './lib'; -export type { ConfigSchema } from './lib'; +export type { ConfigSchema, ConfigVisibility } from './lib'; export { loadConfig } from './loader'; export type { LoadConfigOptions } from './loader'; diff --git a/packages/config-loader/src/lib/schema/filtering.ts b/packages/config-loader/src/lib/schema/filtering.ts index 908e9e4739..74e75f465d 100644 --- a/packages/config-loader/src/lib/schema/filtering.ts +++ b/packages/config-loader/src/lib/schema/filtering.ts @@ -15,7 +15,11 @@ */ import { JsonObject, JsonValue } from '@backstage/config'; -import { ConfigVisibility, DEFAULT_CONFIG_VISIBILITY } from './types'; +import { + ConfigVisibility, + DEFAULT_CONFIG_VISIBILITY, + TransformFunc, +} from './types'; /** * This filters data by visibility by discovering the visibility of each @@ -25,14 +29,20 @@ export function filterByVisibility( data: JsonObject, includeVisibilities: ConfigVisibility[], visibilityByPath: Map, + transformFunc?: TransformFunc, ): JsonObject { function transform(jsonVal: JsonValue, path: string): JsonValue | undefined { - const isVisible = includeVisibilities.includes( - visibilityByPath.get(path) ?? DEFAULT_CONFIG_VISIBILITY, - ); + const visibility = visibilityByPath.get(path) ?? DEFAULT_CONFIG_VISIBILITY; + const isVisible = includeVisibilities.includes(visibility); if (typeof jsonVal !== 'object') { - return isVisible ? jsonVal : undefined; + if (isVisible) { + if (transformFunc) { + return transformFunc(jsonVal, { visibility }); + } + return jsonVal; + } + return undefined; } else if (jsonVal === null) { return undefined; } else if (Array.isArray(jsonVal)) { diff --git a/packages/config-loader/src/lib/schema/index.ts b/packages/config-loader/src/lib/schema/index.ts index bc3c7d8ebc..8cefb93b3c 100644 --- a/packages/config-loader/src/lib/schema/index.ts +++ b/packages/config-loader/src/lib/schema/index.ts @@ -15,4 +15,4 @@ */ export { loadConfigSchema } from './load'; -export type { ConfigSchema } from './types'; +export type { ConfigSchema, ConfigVisibility } from './types'; diff --git a/packages/config-loader/src/lib/schema/load.ts b/packages/config-loader/src/lib/schema/load.ts index d886926647..010317849c 100644 --- a/packages/config-loader/src/lib/schema/load.ts +++ b/packages/config-loader/src/lib/schema/load.ts @@ -18,7 +18,11 @@ import { AppConfig, JsonObject } from '@backstage/config'; import { compileConfigSchemas } from './compile'; import { collectConfigSchemas } from './collect'; import { filterByVisibility } from './filtering'; -import { ConfigSchema, ConfigSchemaPackageEntry } from './types'; +import { + ConfigSchema, + ConfigSchemaPackageEntry, + CONFIG_VISIBILITIES, +} from './types'; type Options = | { @@ -51,7 +55,10 @@ export async function loadConfigSchema( const validate = compileConfigSchemas(schemas); return { - process(configs: AppConfig[], { visiblity } = {}): AppConfig[] { + process( + configs: AppConfig[], + { visiblity, valueTransform } = {}, + ): AppConfig[] { const result = validate(configs); if (result.errors) { throw new Error( @@ -64,7 +71,22 @@ export async function loadConfigSchema( if (visiblity) { processedConfigs = processedConfigs.map(({ data, context }) => ({ context, - data: filterByVisibility(data, visiblity, result.visibilityByPath), + data: filterByVisibility( + data, + visiblity, + result.visibilityByPath, + valueTransform, + ), + })); + } else if (valueTransform) { + processedConfigs = processedConfigs.map(({ data, context }) => ({ + context, + data: filterByVisibility( + data, + Array.from(CONFIG_VISIBILITIES), + result.visibilityByPath, + valueTransform, + ), })); } diff --git a/packages/config-loader/src/lib/schema/types.ts b/packages/config-loader/src/lib/schema/types.ts index 6ab0602fb3..c82036bbf4 100644 --- a/packages/config-loader/src/lib/schema/types.ts +++ b/packages/config-loader/src/lib/schema/types.ts @@ -71,6 +71,14 @@ type ValidationResult = { */ export type ValidationFunc = (configs: AppConfig[]) => ValidationResult; +/** + * A function used to transform primitive configuration values. + */ +export type TransformFunc = ( + value: T, + context: { visibility: ConfigVisibility }, +) => T | undefined; + /** * Options used to process configuration data with a schema. */ @@ -80,6 +88,14 @@ type ConfigProcessingOptions = { * If omitted, the data will not be filtered by visibility. */ visiblity?: ConfigVisibility[]; + + /** + * A transform function that can be used to transform primitive configuration values + * during validation. The value returned from the transform function will be used + * instead of the original value. If the transform returns `undefined`, the value + * will be omitted. + */ + valueTransform?: TransformFunc; }; /**