mirror of
https://github.com/hatchet-dev/hatchet.git
synced 2025-12-31 05:39:41 -06:00
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package datautils
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"reflect"
|
|
"text/template"
|
|
)
|
|
|
|
// RenderTemplateFields recursively processes the input map, rendering any string fields using the data map.
|
|
func RenderTemplateFields(data map[string]interface{}, input map[string]interface{}) (map[string]interface{}, error) {
|
|
output := map[string]interface{}{}
|
|
|
|
for key, val := range input {
|
|
switch v := val.(type) {
|
|
case string:
|
|
tmpl, err := template.New(key).Parse(v)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error creating template for key %s: %v", key, err)
|
|
}
|
|
|
|
var tpl bytes.Buffer
|
|
err = tmpl.Execute(&tpl, data)
|
|
|
|
if err != nil {
|
|
return nil, fmt.Errorf("error executing template for key %s: %v", key, err)
|
|
}
|
|
|
|
res := tpl.String()
|
|
|
|
// if the string can be unmarshalled into a map[string]interface{}, do so
|
|
resMap := map[string]interface{}{}
|
|
|
|
if err := json.Unmarshal(tpl.Bytes(), &resMap); err == nil {
|
|
output[key] = resMap
|
|
|
|
// if the key is "object", the entire input is replaced with the rendered value
|
|
if key == "object" {
|
|
// note we do not recursively render the new input, as it may contain untrusted data.
|
|
return resMap, nil
|
|
}
|
|
} else {
|
|
output[key] = res
|
|
}
|
|
case map[string]interface{}:
|
|
// if we hit a nested map[string]interface{}, render those recursively
|
|
recOut, err := RenderTemplateFields(data, v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
output[key] = recOut
|
|
default:
|
|
if reflect.TypeOf(v).Kind() == reflect.Map {
|
|
// If it's a map but not map[string]interface{}, return an error
|
|
return nil, fmt.Errorf("encountered a map that is not map[string]interface{}: %s", key)
|
|
}
|
|
|
|
// otherwise, just copy the value over
|
|
output[key] = v
|
|
}
|
|
}
|
|
|
|
return output, nil
|
|
}
|