Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for multiple fields in load condition functions #3

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 49 additions & 37 deletions app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ func (c *AppConfig) checkForFieldSetDependencies(fieldSet *FieldSet) []error {
errs := []error{}

for _, loadCondition := range fieldSet.LoadConditions {
fieldSetKey, fieldKey := loadCondition.FieldDependency()
if fieldSetKey == "" && fieldKey == "" {
fieldSetKey, fieldKeys := loadCondition.FieldDependency()
if fieldSetKey == "" && len(fieldKeys) == 0 {
continue
}

Expand All @@ -495,15 +495,17 @@ func (c *AppConfig) checkForFieldSetDependencies(fieldSet *FieldSet) []error {
continue
}

_, found = fieldSetDependency.fieldMap[fieldKey]
if !found {
errs = append(
errs,
fmt.Errorf(
"field-set '%s' field-set dependency field not found: %s_%s",
fieldSet.Key, fieldSetKey, fieldKey,
),
)
for _, fieldKey := range fieldKeys {
_, found = fieldSetDependency.fieldMap[fieldKey]
if !found {
errs = append(
errs,
fmt.Errorf(
"field-set '%s' field-set dependency field not found: %s_%s",
fieldSet.Key, fieldSetKey, fieldKey,
),
)
}
}
}

Expand All @@ -523,9 +525,9 @@ func (c *AppConfig) checkForFieldDependencies(field *Field, parent *FieldSet) er

var found bool

fieldSetKey, fieldKey := loadCondition.FieldDependency()
fieldSetKey, fieldKeys := loadCondition.FieldDependency()

if fieldSetKey == "" && fieldKey == "" {
if fieldSetKey == "" && len(fieldKeys) == 0 {
continue
}

Expand All @@ -543,11 +545,13 @@ func (c *AppConfig) checkForFieldDependencies(field *Field, parent *FieldSet) er
}
}

if _, found = fieldSetDependency.fieldMap[fieldKey]; !found {
return fmt.Errorf(
"field-set '%s' field '%s' field-set field not found: %s_%s",
parent.Key, field.Key, fieldSetKey, fieldKey,
)
for _, fieldKey := range fieldKeys {
if _, found = fieldSetDependency.fieldMap[fieldKey]; !found {
return fmt.Errorf(
"field-set '%s' field '%s' field-set field not found: %s_%s",
parent.Key, field.Key, fieldSetKey, fieldKey,
)
}
}
}
}
Expand Down Expand Up @@ -648,23 +652,27 @@ func (c *AppConfig) shouldLoadFieldSet(fieldSet *FieldSet) (bool, error) {
break
}

conditionFieldSetKey, conditionFieldSetFieldKey := loadCondition.FieldDependency()
if conditionFieldSetKey != "" && conditionFieldSetFieldKey != "" {
fieldValue, err := c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
var err error

conditionFieldSetKey, conditionFieldSetFieldKeys := loadCondition.FieldDependency()
if conditionFieldSetKey != "" && len(conditionFieldSetFieldKeys) > 0 {
fieldValues := map[string]any{}

for _, conditionFieldSetFieldKey := range conditionFieldSetFieldKeys {
fieldValues[conditionFieldSetFieldKey], err = c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
}
}

loadFieldSet, err = loadCondition.Load(fieldValue)
loadFieldSet, err = loadCondition.Load(fieldValues)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
}

continue
}

var err error

loadFieldSet, err = loadCondition.Load(nil)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
Expand All @@ -686,27 +694,31 @@ func (c *AppConfig) shouldLoadField(field *Field, fieldSetKey string) (bool, err
break
}

conditionFieldSetKey, conditionFieldSetFieldKey := loadCondition.FieldDependency()
conditionFieldSetKey, conditionFieldSetFieldKeys := loadCondition.FieldDependency()
if conditionFieldSetKey == "" {
conditionFieldSetKey = fieldSetKey
}

if conditionFieldSetKey != "" && conditionFieldSetFieldKey != "" {
fieldValue, err := c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
var err error

if conditionFieldSetKey != "" && len(conditionFieldSetFieldKeys) > 0 {
fieldValues := map[string]any{}

for _, conditionFieldSetFieldKey := range conditionFieldSetFieldKeys {
fieldValues[conditionFieldSetFieldKey], err = c.getFieldValue(conditionFieldSetKey, conditionFieldSetFieldKey, "any")
if err != nil {
return false, fmt.Errorf("problem getting field value for load condition: %w", err)
}
}

loadField, err = loadCondition.Load(fieldValue)
loadField, err = loadCondition.Load(fieldValues)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
}

continue
}

var err error

loadField, err = loadCondition.Load(nil)
if err != nil {
return false, fmt.Errorf("problem getting load condition outcome: %w", err)
Expand Down Expand Up @@ -867,11 +879,11 @@ func (c *AppConfig) fieldHelpString(fields map[string]*fieldEntry, key string) s
}

for _, condition := range loadConditions {
fieldSetDependency, fieldDependency := condition.FieldDependency()
if fieldSetDependency != "" && fieldDependency != "" {
fieldSetDependency, fieldDependencies := condition.FieldDependency()
if fieldSetDependency != "" && len(fieldDependencies) > 0 {
builder.WriteString(spaceBuffer)
builder.WriteString(
fmt.Sprintf("Loading depends on field: '%s_%s'\n", fieldSetDependency, fieldDependency),
fmt.Sprintf("Loading depends on field: '%s_%s'\n", fieldSetDependency, fieldDependencies),
)
} else {
builder.WriteString(spaceBuffer)
Expand Down
48 changes: 24 additions & 24 deletions app_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ func TestAppConfigHelpString(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: stringFieldKey,
Condition: func(fieldValue any) (bool, error) {
val, ok := fieldValue.(string)
FieldKeys: []string{stringFieldKey},
Condition: func(fieldValues map[string]any) (bool, error) {
val, ok := fieldValues[stringFieldKey].(string)
if !ok {
return false, fmt.Errorf("unexpected field value type")
}
Expand Down Expand Up @@ -159,9 +159,9 @@ func TestAppConfig(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: "app",
FieldKey: "connect_sqlite",
Condition: func(fieldValue any) (bool, error) {
val, ok := fieldValue.(bool)
FieldKeys: []string{"connect_sqlite"},
Condition: func(fieldValues map[string]any) (bool, error) {
val, ok := fieldValues["connect_sqlite"].(bool)
if !ok {
return false, fmt.Errorf("unexpected field-type value")
}
Expand Down Expand Up @@ -342,8 +342,8 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: defaultFieldSetLoadAppOneKey,
Condition: func(fieldValue any) (bool, error) {
FieldKeys: []string{defaultFieldSetLoadAppOneKey},
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand All @@ -356,8 +356,8 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
FieldKey: defaultFieldSetLoadAppTwoKey,
Condition: func(fieldValue any) (bool, error) {
FieldKeys: []string{defaultFieldSetLoadAppTwoKey},
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand All @@ -370,7 +370,7 @@ func TestAppConfigWithLoadConditions(t *testing.T) {
LoadConditions: bconf.LoadConditions{
&bconf.FieldCondition{
FieldSetKey: defaultFieldSetKey,
Condition: func(fieldValue any) (bool, error) {
Condition: func(fieldValues map[string]any) (bool, error) {
return true, nil
},
},
Expand Down Expand Up @@ -444,21 +444,21 @@ func TestAppConfigWithFieldLoadConditions(t *testing.T) {
fieldSetWithInternalFieldDependencies := bconf.FSB().Key(fieldSetOneKey).Fields(
bconf.FB().Key(fieldAKey).Type(bconf.String).Default("postgres").Create(),
bconf.FB().Key(fieldBKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
bconf.FB().Key(fieldCKey).Type(bconf.String).LoadConditions(
bconf.
FCB().
FieldKey(fieldAKey).
AddFieldKey(fieldAKey).
FieldSetKey(fieldSetOneKey).
Condition(func(val any) (bool, error) {
Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
bconf.FB().Key(fieldDKey).Type(bconf.String).Default("should_not_be_overridden").LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return false, nil
}).Create(),
).Create(),
Expand Down Expand Up @@ -490,15 +490,15 @@ func TestAppConfigWithFieldLoadConditions(t *testing.T) {
fieldSetWithMissingInternalFieldDependencies := bconf.FSB().Key(fieldSetThreeKey).Fields(
bconf.FB().Key(fieldFKey).Type(bconf.String).Create(),
bconf.FB().Key(fieldGKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey(fieldAKey).Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey(fieldAKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
).Create()

fieldSetWithMissingExternalFieldDependencies := bconf.FSB().Key(fieldSetFourKey).Fields(
bconf.FB().Key(fieldAKey).Type(bconf.String).LoadConditions(
bconf.FCB().FieldSetKey("missing").FieldKey(fieldBKey).Condition(func(val any) (bool, error) {
bconf.FCB().FieldSetKey("missing").AddFieldKey(fieldBKey).Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create(),
Expand Down Expand Up @@ -583,8 +583,8 @@ func TestAppConfigAddField(t *testing.T) {
}

fieldMissingLoadCondition := bconf.FB().Key("field_missing_load_condition").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("missing_key").Condition(
func(val any) (bool, error) {
bconf.FCB().AddFieldKey("missing_key").Condition(
func(_ map[string]any) (bool, error) {
return true, nil
},
).Create(),
Expand Down Expand Up @@ -644,8 +644,8 @@ func TestAppConfigLoadFieldSet(t *testing.T) {
errs = appConfig.AddFieldSet(bconf.FSB().Key("bad_field_condition_conditional").Fields(
bconf.FB().Key("some_key").Type(bconf.String).Default("value").Create(),
).LoadConditions(
bconf.NewFieldConditionBuilder().FieldSetKey("default").FieldKey("field_key").Condition(
func(fieldValue any) (bool, error) {
bconf.NewFieldConditionBuilder().FieldSetKey("default").AddFieldKey("field_key").Condition(
func(_ map[string]any) (bool, error) {
return true, fmt.Errorf("condition error")
},
).Create(),
Expand Down Expand Up @@ -715,7 +715,7 @@ func TestAppConfigLoadField(t *testing.T) {
}

addedFieldC := bconf.FB().Key("field_c").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_b").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_b").Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create()
Expand All @@ -738,7 +738,7 @@ func TestAppConfigLoadField(t *testing.T) {
os.Setenv("STANDARD_D_FIELD_D", "expected_value")

addedFieldD := bconf.FB().Key("field_d").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_a").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_a").Condition(func(_ map[string]any) (bool, error) {
return true, nil
}).Create(),
).Create()
Expand All @@ -762,7 +762,7 @@ func TestAppConfigLoadField(t *testing.T) {

// A test case for loading a field with a falsy field load condition
addedFieldE := bconf.FB().Key("field_e").Type(bconf.String).LoadConditions(
bconf.FCB().FieldKey("field_a").Condition(func(val any) (bool, error) {
bconf.FCB().AddFieldKey("field_a").Condition(func(_ map[string]any) (bool, error) {
return false, nil
}).Create(),
).Create()
Expand Down
16 changes: 8 additions & 8 deletions field_condition.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package bconf
import "fmt"

type FieldCondition struct {
Condition func(fieldValue any) (bool, error)
Condition func(fieldValues map[string]any) (bool, error)
FieldSetKey string
FieldKey string
FieldKeys []string
}

func (c *FieldCondition) Clone() LoadCondition {
Expand All @@ -14,12 +14,12 @@ func (c *FieldCondition) Clone() LoadCondition {
return &clone
}

func (c *FieldCondition) FieldDependency() (fieldSetKey, fieldKey string) {
return c.FieldSetKey, c.FieldKey
func (c *FieldCondition) FieldDependency() (fieldSetKey string, fieldKeys []string) {
return c.FieldSetKey, c.FieldKeys
}

func (c *FieldCondition) Load(value any) (bool, error) {
return c.Condition(value)
func (c *FieldCondition) Load(values map[string]any) (bool, error) {
return c.Condition(values)
}

func (c *FieldCondition) Validate() []error {
Expand All @@ -29,8 +29,8 @@ func (c *FieldCondition) Validate() []error {
errs = append(errs, fmt.Errorf("field-set key required for field condition"))
}

if c.FieldKey == "" {
errs = append(errs, fmt.Errorf("field key required for field condition"))
if len(c.FieldKeys) == 0 {
errs = append(errs, fmt.Errorf("at least one field key required for field condition"))
}

return errs
Expand Down
6 changes: 3 additions & 3 deletions field_condition_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ func (b *FieldConditionBuilder) FieldSetKey(value string) *FieldConditionBuilder
return b
}

func (b *FieldConditionBuilder) FieldKey(value string) *FieldConditionBuilder {
func (b *FieldConditionBuilder) AddFieldKey(value string) *FieldConditionBuilder {
b.init()
b.condition.FieldKey = value
b.condition.FieldKeys = append(b.condition.FieldKeys, value)

return b
}

func (b *FieldConditionBuilder) Condition(value func(fieldValue any) (bool, error)) *FieldConditionBuilder {
func (b *FieldConditionBuilder) Condition(value func(fieldValues map[string]any) (bool, error)) *FieldConditionBuilder {
b.init()
b.condition.Condition = value

Expand Down
8 changes: 4 additions & 4 deletions field_condition_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,14 @@ func TestFieldConditionBuilderKeys(t *testing.T) {
t.Fatalf("unexpected field-set key value '%s', expected '%s'", fsKey, fieldSetKey)
}

condition = bconf.FCB().FieldKey(fieldKey).Create()
if _, fKey := condition.FieldDependency(); fKey != fieldKey {
t.Fatalf("unexpected field key value '%s', expected '%s'", fKey, fieldKey)
condition = bconf.FCB().AddFieldKey(fieldKey).Create()
if _, fKeys := condition.FieldDependency(); fKeys[0] != fieldKey {
t.Fatalf("unexpected field key value '%s', expected '%s'", fKeys[0], fieldKey)
}
}

func TestFieldConditionBuilderCondition(t *testing.T) {
condition := func(fieldValue any) (bool, error) {
condition := func(_ map[string]any) (bool, error) {
return true, nil
}
fieldCondition := bconf.FCB().Condition(condition).Create()
Expand Down
Loading