config-loader: add support for transforming values during schema processing

This commit is contained in:
Patrik Oldsberg
2020-11-14 15:48:02 +01:00
parent 051e0fd17e
commit 49ab961b8b
5 changed files with 58 additions and 10 deletions
+1 -1
View File
@@ -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';
@@ -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<string, ConfigVisibility>,
transformFunc?: TransformFunc<number | string | boolean>,
): 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)) {
@@ -15,4 +15,4 @@
*/
export { loadConfigSchema } from './load';
export type { ConfigSchema } from './types';
export type { ConfigSchema, ConfigVisibility } from './types';
+25 -3
View File
@@ -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,
),
}));
}
@@ -71,6 +71,14 @@ type ValidationResult = {
*/
export type ValidationFunc = (configs: AppConfig[]) => ValidationResult;
/**
* A function used to transform primitive configuration values.
*/
export type TransformFunc<T extends number | string | boolean> = (
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<any>;
};
/**