Appearance
Schema: Data Transformation
Konfigo's transform directives modify configuration structure and content after merging but before validation. Transformations process sequentially, with each operation receiving the output from the previous one.
Processing Order
- Variable substitution in transform directives
- Execute transformations in list order
- Each transformation modifies the configuration state
- Results passed to validation (if defined)
Transformation Types
Konfigo provides eight built-in transformer types:
renameKey- Move values between configuration pathschangeCase- Convert string values to different case formatsaddKeyPrefix- Add prefixes to all keys in a mapsetValue- Set values at configuration pathsaddKeySuffix- Add suffixes to all keys in a mapdeleteKey- Remove keys from configurationtrim- Trim whitespace or characters from stringsreplaceKey- Replace values using another configuration path
1. renameKey - Move Configuration Keys
Moves a value from one path to another, creating nested structures as needed.
Structure:
yaml
transform:
- type: "renameKey"
from: "old.path.to.key"
to: "new.path.to.key"Fields:
type(Required):"renameKey"from(Required): Source path (must exist)to(Required): Destination path (created if needed)
Example from Tests:
yaml
# Input config:
legacy:
api_endpoint: "HTTP://OLD-DOMAIN.COM/api"
# Transform:
transform:
- type: "renameKey"
from: "legacy.api_endpoint"
to: "service.url"
# Result:
service:
url: "HTTP://OLD-DOMAIN.COM/api"
# legacy key removed2. changeCase - Modify String Case
Converts string values to different case formats.
Structure:
yaml
transform:
- type: "changeCase"
path: "path.to.string.value"
case: "lower" # upper, lower, snake, camelFields:
type(Required):"changeCase"path(Required): Path to string valuecase(Required): Target case format
Supported Cases:
"upper": UPPERCASE"lower": lowercase"snake": snake_case"camel": camelCase
Example from Tests:
yaml
# Input config:
service:
url: "HTTP://OLD-DOMAIN.COM/api"
# Transform:
transform:
- type: "changeCase"
path: "service.url"
case: "lower"
# Result:
service:
url: "http://old-domain.com/api"3. addKeyPrefix - Prefix Map Keys
Adds a prefix to all keys within a map object.
Structure:
yaml
transform:
- type: "addKeyPrefix"
path: "path.to.map"
prefix: "prefix_"Fields:
type(Required):"addKeyPrefix"path(Required): Path to map objectprefix(Required): String to prepend to keys
Example from Tests:
yaml
# Input config:
service:
url: "http://old-domain.com/api"
environment: "prod"
# Transform:
vars:
- name: "ENV_PREFIX"
value: "prod"
transform:
- type: "addKeyPrefix"
path: "service"
prefix: "${ENV_PREFIX}_"
# Result:
service:
prod_url: "http://old-domain.com/api"
prod_environment: "prod"4. setValue - Set Configuration Values
Sets any value at a specified path, with variable substitution support.
Structure:
yaml
transform:
- type: "setValue"
path: "path.to.key"
value: "any value type"Fields:
type(Required):"setValue"path(Required): Target path (created if needed)value(Required): Value to set (any type, strings get variable substitution)
Examples from Tests:
String Value with Variables:
yaml
vars:
- name: "ENV_PREFIX"
value: "prod"
transform:
- type: "setValue"
path: "service.environment"
value: "${ENV_PREFIX}"
# Result:
service:
environment: "prod"Complex Object Value:
yaml
transform:
- type: "setValue"
path: "app.settings"
value:
enabled: true
features: ["auth", "logging"]
timeout: 30
# Result:
app:
settings:
enabled: true
features: ["auth", "logging"]
timeout: 305. addKeySuffix - Suffix Map Keys
Adds a suffix to all keys within a map object.
Structure:
yaml
transform:
- type: "addKeySuffix"
path: "path.to.map"
suffix: "_suffix"Fields:
type(Required):"addKeySuffix"path(Required): Path to map objectsuffix(Required): String to append to keys
Example:
yaml
# Input config:
database:
host: "localhost"
port: 5432
# Transform:
transform:
- type: "addKeySuffix"
path: "database"
suffix: "_prod"
# Result:
database:
host_prod: "localhost"
port_prod: 54326. deleteKey - Remove Configuration Keys
Removes a key at the specified path from the configuration.
Structure:
yaml
transform:
- type: "deleteKey"
path: "path.to.key"Fields:
type(Required):"deleteKey"path(Required): Path to key to delete
Example:
yaml
# Input config:
app:
secret: "sensitive_data"
name: "myapp"
# Transform:
transform:
- type: "deleteKey"
path: "app.secret"
# Result:
app:
name: "myapp"7. trim - Trim String Values
Trims whitespace or specified characters from string values.
Structure:
yaml
transform:
- type: "trim"
path: "path.to.string"
pattern: " \t\n" # Optional, defaults to whitespaceFields:
type(Required):"trim"path(Required): Path to string valuepattern(Optional): Characters to trim (defaults to whitespace)
Examples:
Default Whitespace Trimming:
yaml
# Input config:
api:
endpoint: " https://api.example.com "
# Transform:
transform:
- type: "trim"
path: "api.endpoint"
# Result:
api:
endpoint: "https://api.example.com"Custom Pattern Trimming:
yaml
# Input config:
token:
value: "---secret-token---"
# Transform:
transform:
- type: "trim"
path: "token.value"
pattern: "-"
# Result:
token:
value: "secret-token"8. replaceKey - Replace with Target Value
Replaces a value at one path with a value from another path, then deletes the source.
Structure:
yaml
transform:
- type: "replaceKey"
path: "destination.path"
target: "source.path"Fields:
type(Required):"replaceKey"path(Required): Destination path where value will be placedtarget(Required): Source path to take value from (will be deleted)
Example:
yaml
# Input config:
temp:
newEndpoint: "https://api.v2.example.com"
api:
endpoint: "https://api.v1.example.com"
# Transform:
transform:
- type: "replaceKey"
path: "api.endpoint"
target: "temp.newEndpoint"
# Result:
api:
endpoint: "https://api.v2.example.com"
# temp section is deletedCombined Transformations
Complete Example with Multiple Transformers:
yaml
# Input config:
legacy:
api_endpoint: " HTTP://OLD-DOMAIN.COM/api "
api_key: "secret123"
database:
host: "db-server"
temp:
newPort: 8080
# Schema with transformations:
vars:
- name: "ENV_PREFIX"
value: "prod"
transform:
# Rename and clean up API endpoint
- type: "renameKey"
from: "legacy.api_endpoint"
to: "service.url"
- type: "trim"
path: "service.url"
- type: "changeCase"
path: "service.url"
case: "lower"
# Add environment and prefix keys
- type: "setValue"
path: "service.environment"
value: "${ENV_PREFIX}"
- type: "addKeyPrefix"
path: "service"
prefix: "${ENV_PREFIX}_"
# Replace port with new value and clean up
- type: "replaceKey"
path: "database.port"
target: "temp.newPort"
- type: "addKeySuffix"
path: "database"
suffix: "_config"
# Remove sensitive data
- type: "deleteKey"
path: "legacy.api_key"
# Final result:
database:
host_config: "db-server"
port_config: 8080
prod_service:
prod_url: "http://old-domain.com/api"
prod_environment: "prod"
# legacy section cleaned up (api_key deleted)
legacy: {}Advanced Transformation Patterns
Conditional Value Setting
Use variables to set values conditionally:
yaml
vars:
- name: "ENVIRONMENT"
fromEnv: "NODE_ENV"
defaultValue: "development"
- name: "DEBUG_MODE"
value: "true"
# Only in dev
transform:
- type: "setValue"
path: "app.debug"
value: "${DEBUG_MODE}"Restructuring Legacy Configurations
Transform old configuration formats:
yaml
transform:
# Migrate old database config
- type: "renameKey"
from: "db.connection_string"
to: "database.url"
- type: "renameKey"
from: "db.max_connections"
to: "database.pool.max"
# Add new required fields
- type: "setValue"
path: "database.pool.min"
value: 5Environment-Specific Transformations
Apply different transformations per environment:
yaml
vars:
- name: "ENV"
fromEnv: "ENVIRONMENT"
defaultValue: "dev"
transform:
- type: "setValue"
path: "app.environment"
value: "${ENV}"
- type: "addKeyPrefix"
path: "database"
prefix: "${ENV}_"Error Handling
Common transformation errors:
Path Not Found
yaml
transform:
- type: "renameKey"
from: "missing.path" # ERROR: path doesn't exist
to: "new.path"Type Mismatch
yaml
transform:
- type: "changeCase"
path: "numeric.value" # ERROR: value is not a string
case: "lower"Invalid Case Format
yaml
transform:
- type: "changeCase"
path: "string.value"
case: "invalid" # ERROR: unsupported case formatNon-Map Prefix Target
yaml
transform:
- type: "addKeyPrefix"
path: "string.value" # ERROR: value is not a map
prefix: "pre_"Best Practices
- Order Matters: Plan transformation sequence carefully
- Path Validation: Ensure source paths exist before renaming
- Variable Usage: Leverage variables for dynamic prefixes and values
- Error Testing: Test with invalid inputs to verify error handling
- Documentation: Document complex transformation chainsyaml
transform: - type: "changeCase" path: "path.to.string.value" # Dot-separated path to the string value. case: "snake" # Target case: "upper", "lower", "snake", "camel".
- Fields:
type(Required):"changeCase"path(Required, string): The dot-separated path to the string value to be modified.case(Required, string): The target case format. Supported values:"upper": Converts to UPPERCASE."lower": Converts to lowercase."snake": Converts to snake_case."camel": Converts to camelCase (lower camel case).
- Behavior:
- Retrieves the value from
path. - If the path is not found or the value is not a string, an error occurs.
- Converts the string to the specified
case. - Updates the value at
pathwith the new cased string.
- Retrieves the value from
- Example:yaml
# Config before: { "apiSettings": { "RequestTimeout": "ThirtySeconds" } } transform: - type: "changeCase" path: "apiSettings.RequestTimeout" case: "snake" # Config after: { "apiSettings": { "RequestTimeout": "thirty_seconds" } }
3. addKeyPrefix
Adds a prefix to all keys within a map located at a specified path.
- Structure:yaml
transform: - type: "addKeyPrefix" path: "path.to.map.object" # Dot-separated path to the map. prefix: "my_prefix_" # String to prepend to each key in the map. - Fields:
type(Required):"addKeyPrefix"path(Required, string): The dot-separated path to the map object whose keys will be prefixed.prefix(Required, string): The string to prepend to each key within the map atpath.
- Behavior:
- Retrieves the value from
path. - If the path is not found or the value is not a map, an error occurs.
- Creates a new map where each key from the original map is prepended with
prefix. - Updates the value at
pathwith this new map.
- Retrieves the value from
- Example:yaml
# Config before: { "settings": { "timeout": 30, "retries": 3 } } transform: - type: "addKeyPrefix" path: "settings" prefix: "http_" # Config after: { "settings": { "http_timeout": 30, "http_retries": 3 } }
4. setValue
Sets a specific value at a given path, potentially overwriting an existing value or creating the path if it doesn't exist. The value can be of any valid YAML/JSON type (string, number, boolean, list, map).
- Structure:yaml
transform: - type: "setValue" path: "path.to.target.key" # Dot-separated path where the value will be set. value: "New Static Value" # The value to set. Can be any type. # If a string, it undergoes variable substitution.yamltransform: - type: "setValue" path: "feature.flags" value: newToggle: true betaFeature: false - Fields:
type(Required):"setValue"path(Required, string): The dot-separated path where thevaluewill be set.value(Required, any): The value to set at thepath. This can be a simple literal (string, number, boolean) or a complex nested structure (map, list). Ifvalueis a string, it will undergo${VAR_NAME}substitution before being set.
- Behavior:
- Sets the provided
valueat the specifiedpath. - If the path or parts of it do not exist, they are created.
- If a value already exists at
path, it is overwritten.
- Sets the provided
- Example (String Value with Variable Substitution):yaml
# Schema vars: # vars: # - name: "ADMIN_EMAIL" # value: "admin@example.com" # Config before: { } transform: - type: "setValue" path: "contact.admin" value: "Email: ${ADMIN_EMAIL}" # Config after: { "contact": { "admin": "Email: admin@example.com" } } - Example (Complex Value):yaml
# Config before: { "app": { "name": "MyApp" } } transform: - type: "setValue" path: "app.settings.notifications" value: enabled: true channels: ["email", "sms"] # Config after: # { # "app": { # "name": "MyApp", # "settings": { # "notifications": { # "enabled": true, # "channels": ["email", "sms"] # } # } # } # }
Example Combining Transformations
yaml
# schema.yml
vars:
- name: "ENV_PREFIX"
value: "prod"
transform:
- type: "renameKey"
from: "legacy.api_endpoint"
to: "service.url"
- type: "changeCase"
path: "service.url" # Assuming it's a string like "HTTP://OLD-DOMAIN.COM"
case: "lower"
- type: "setValue"
path: "service.environment"
value: "${ENV_PREFIX}"
- type: "addKeyPrefix"
path: "service" # Assuming service map now exists
prefix: "${ENV_PREFIX}_"
# Initial config (merged from sources):
# {
# "legacy": { "api_endpoint": "HTTP://OLD-DOMAIN.COM/api" },
# "other_setting": 123
# }
# Expected final config (YAML):
# other_setting: 123
# prod_service:
# environment: prod
# url: http://old-domain.com/apiThis sequence first renames legacy.api_endpoint to service.url. Then, it changes the case of the string at service.url. After that, it sets service.environment using a variable. Finally, it prefixes all keys within the service map (which now contains url and environment) with prod_.