diff --git a/pkg/config/apply.go b/pkg/environment/apply.go similarity index 69% rename from pkg/config/apply.go rename to pkg/environment/apply.go index 7eac9cfc..d15115f4 100644 --- a/pkg/config/apply.go +++ b/pkg/environment/apply.go @@ -10,23 +10,23 @@ import ( var placeholder = regexp.MustCompile(`\$\{\{\s*([^\}]*)\s*\}\}`) -// Apply applies the configuration represented by 'config' to the input value 'val'. -// It replaces placeholders in the input value with corresponding values from the configuration. -func Apply(val any, config *Config) (any, error) { - config.mu.RLock() - defer config.mu.RUnlock() +// Apply applies the environment represented by 'environment' to the input value 'val'. +// It replaces placeholders in the input value with corresponding values from the environment. +func Apply(val any, environment *Environment) (any, error) { + environment.mu.RLock() + defer environment.mu.RUnlock() v := reflect.ValueOf(val) result := deepUnSpecify(v) - if err := applyRecursive(result, config.data); err != nil { + if err := applyRecursive(result, environment.data); err != nil { return nil, err } return result.Interface(), nil } -func applyRecursive(node reflect.Value, config map[string]any) error { +func applyRecursive(node reflect.Value, environment map[string]any) error { switch node.Kind() { case reflect.Map: for _, key := range node.MapKeys() { @@ -35,14 +35,14 @@ func applyRecursive(node reflect.Value, config map[string]any) error { switch value.Kind() { case reflect.String: strValue := value.String() - newValue, err := replacePlaceholders(strValue, config) + newValue, err := replacePlaceholders(strValue, environment) if err != nil { return err } node.SetMapIndex(key, reflect.ValueOf(newValue)) case reflect.Map, reflect.Slice: - if err := applyRecursive(value, config); err != nil { + if err := applyRecursive(value, environment); err != nil { return err } } @@ -50,7 +50,7 @@ func applyRecursive(node reflect.Value, config map[string]any) error { case reflect.Slice: for i := 0; i < node.Len(); i++ { elem := reflect.ValueOf(node.Index(i).Interface()) - err := applyRecursive(elem, config) + err := applyRecursive(elem, environment) if err != nil { return err } @@ -59,14 +59,14 @@ func applyRecursive(node reflect.Value, config map[string]any) error { return nil } -func replacePlaceholders(input string, config map[string]any) (any, error) { +func replacePlaceholders(input string, environment map[string]any) (any, error) { matches := placeholder.FindAllStringSubmatch(input, -1) if len(matches) == 0 { return input, nil } if len(matches) == 1 { - return evaluateExpression(matches[0][1], config) + return evaluateExpression(matches[0][1], environment) } return placeholder.ReplaceAllStringFunc(input, func(match string) string { @@ -76,7 +76,7 @@ func replacePlaceholders(input string, config map[string]any) (any, error) { } expression := matches[1] - value, err := evaluateExpression(expression, config) + value, err := evaluateExpression(expression, environment) if err != nil { return match } @@ -85,12 +85,12 @@ func replacePlaceholders(input string, config map[string]any) (any, error) { }), nil } -func evaluateExpression(expression string, config map[string]any) (any, error) { +func evaluateExpression(expression string, environment map[string]any) (any, error) { exp, err := jsonata.Compile(expression) if err != nil { return nil, err } - exp.RegisterVars(config) + exp.RegisterVars(environment) return exp.Eval(nil) } diff --git a/pkg/config/appy_test.go b/pkg/environment/appy_test.go similarity index 100% rename from pkg/config/appy_test.go rename to pkg/environment/appy_test.go diff --git a/pkg/config/config.go b/pkg/environment/environment.go similarity index 65% rename from pkg/config/config.go rename to pkg/environment/environment.go index 4d4c0850..5624c2ad 100644 --- a/pkg/config/config.go +++ b/pkg/environment/environment.go @@ -1,28 +1,29 @@ package config import ( + "fmt" "reflect" "strings" "sync" ) -// Config represents the configuration of your application. -type Config struct { +// Environment represents the environment of your application. +type Environment struct { data map[string]any mu sync.RWMutex } var typeAny = reflect.TypeOf((*any)(nil)).Elem() -// New creates a new configuration instance. -func New() *Config { - return &Config{ +// New creates a new environment instance. +func New() *Environment { + return &Environment{ data: make(map[string]any), } } -// Set sets the value for the specified key in the configuration. -func (c *Config) Set(key string, val any) bool { +// Set sets the value for the specified key in the environment. +func (c *Environment) Set(key string, val any) error { c.mu.Lock() defer c.mu.Unlock() @@ -34,12 +35,12 @@ func (c *Config) Set(key string, val any) bool { t := reflect.ValueOf(token) if node.Kind() != reflect.Map || node.Type().Key().Kind() != reflect.String { - return false + return fmt.Errorf("invalid map type for key %s", key) } if i == len(tokens)-1 { node.SetMapIndex(t, v) - return true + return nil } child := node.MapIndex(t) @@ -49,12 +50,12 @@ func (c *Config) Set(key string, val any) bool { } node = reflect.ValueOf(child.Interface()) } - return false + return nil } -// Get retrieves the value for the specified key from the configuration. +// Get retrieves the value for the specified key from the environment. // If the key is not present, it returns a default value and a boolean indicating the key's existence. -func (c *Config) Get(key string) (any, bool) { +func (c *Environment) Get(key string) (any, bool) { c.mu.RLock() defer c.mu.RUnlock() @@ -78,17 +79,28 @@ func (c *Config) Get(key string) (any, bool) { return node.Interface(), true } -// Delete removes the specified key from the configuration. -func (c *Config) Delete(key string) bool { +// Delete removes the specified key from the environment. +func (c *Environment) Delete(key string) { c.mu.Lock() defer c.mu.Unlock() tokens := strings.Split(key, ".") - return c.deleteRecursive(reflect.ValueOf(c.data), tokens) + c.deleteRecursive(reflect.ValueOf(c.data), tokens) +} + +// GetData returns a read-only copy of the environment data. +func (c *Environment) GetData() map[string]any { + c.mu.RLock() + defer c.mu.RUnlock() + + result := make(map[string]any, len(c.data)) + for k, v := range c.data { + result[k] = v + } + return result } -// deleteRecursive is a recursive helper function for Delete. -func (c *Config) deleteRecursive(node reflect.Value, tokens []string) bool { +func (c *Environment) deleteRecursive(node reflect.Value, tokens []string) bool { t := reflect.ValueOf(tokens[0]) if node.Kind() != reflect.Map || node.Type().Key().Kind() != reflect.String { diff --git a/pkg/config/config_test.go b/pkg/environment/environment_test.go similarity index 64% rename from pkg/config/config_test.go rename to pkg/environment/environment_test.go index a56cce2e..13ab0a16 100644 --- a/pkg/config/config_test.go +++ b/pkg/environment/environment_test.go @@ -8,8 +8,8 @@ import ( "github.com/stretchr/testify/assert" ) -func TestConfig_GetAndSetAndDelete(t *testing.T) { - c := New() +func TestEnvironment_GetAndSetAndDelete(t *testing.T) { + env := New() key1 := faker.Word() key2 := faker.Word() @@ -17,21 +17,21 @@ func TestConfig_GetAndSetAndDelete(t *testing.T) { key := fmt.Sprintf("%s.%s", key1, key2) value := faker.Word() - c.Set(key, value) + env.Set(key, value) - r1, ok := c.Get(key) + r1, ok := env.Get(key) assert.True(t, ok) assert.Equal(t, value, r1) - _, ok = c.Get(key1) + _, ok = env.Get(key1) assert.True(t, ok) - c.Delete(key) + env.Delete(key) - r2, ok := c.Get(key) + r2, ok := env.Get(key) assert.False(t, ok) assert.Nil(t, r2) - _, ok = c.Get(key1) + _, ok = env.Get(key1) assert.False(t, ok) }