From f4b3d8f532a73be2a5ca436f0d69feb9745cbb74 Mon Sep 17 00:00:00 2001 From: William Petit Date: Tue, 27 Sep 2022 22:20:44 +0200 Subject: [PATCH] feat: aggregate defaults and values - Output merged defaults and values - Add "check" command --- go.mod | 4 +- go.sum | 8 +- internal/command/check.go | 49 + internal/command/check_test.go | 87 + internal/command/common.go | 42 + internal/command/edit.go | 9 +- internal/command/get.go | 4 +- internal/command/root.go | 1 + internal/command/set.go | 4 +- internal/command/testdata/check/defaults.json | 5 + internal/command/testdata/check/schema.json | 17 + .../command/testdata/check/values-nok.json | 5 + .../command/testdata/check/values-ok.json | 3 + internal/jsonpointer/delete_test.go | 10 +- internal/jsonpointer/set_test.go | 67 +- internal/jsonpointer/testdata/set/nested.json | 7 +- internal/merge/merge.go | 91 + internal/merge/merge_test.go | 69 + internal/server/route.go | 6 +- .../blocks/form_input_array.html.tmpl | 2 +- .../blocks/form_input_boolean.html.tmpl | 2 +- .../blocks/form_input_number.html.tmpl | 2 +- .../blocks/form_input_string.html.tmpl | 2 +- internal/server/template/template.go | 13 +- package-lock.json | 2784 ++++++++++++++++- package.json | 1 - 26 files changed, 3229 insertions(+), 65 deletions(-) create mode 100644 internal/command/check.go create mode 100644 internal/command/check_test.go create mode 100644 internal/command/testdata/check/defaults.json create mode 100644 internal/command/testdata/check/schema.json create mode 100644 internal/command/testdata/check/values-nok.json create mode 100644 internal/command/testdata/check/values-ok.json create mode 100644 internal/merge/merge.go create mode 100644 internal/merge/merge_test.go diff --git a/go.mod b/go.mod index b6c65be..79bb207 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.18 require ( github.com/Masterminds/sprig/v3 v3.2.2 github.com/hashicorp/hcl/v2 v2.12.0 + github.com/imdario/mergo v0.3.13 github.com/pkg/errors v0.9.1 github.com/urfave/cli/v2 v2.4.0 github.com/zclconf/go-cty v1.8.0 @@ -18,7 +19,6 @@ require ( github.com/google/go-cmp v0.3.1 // indirect github.com/google/uuid v1.1.1 // indirect github.com/huandu/xstrings v1.3.1 // indirect - github.com/imdario/mergo v0.3.11 // indirect github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect github.com/mitchellh/reflectwalk v1.0.0 // indirect @@ -34,5 +34,5 @@ require ( github.com/go-chi/chi v1.5.4 github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b + gopkg.in/yaml.v3 v3.0.1 ) diff --git a/go.sum b/go.sum index 5b99ef9..d37f5a6 100644 --- a/go.sum +++ b/go.sum @@ -31,8 +31,9 @@ github.com/hashicorp/hcl/v2 v2.12.0 h1:PsYxySWpMD4KPaoJLnsHwtK5Qptvj/4Q6s0t4sUxZ github.com/hashicorp/hcl/v2 v2.12.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -100,5 +101,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/command/check.go b/internal/command/check.go new file mode 100644 index 0000000..6b619e3 --- /dev/null +++ b/internal/command/check.go @@ -0,0 +1,49 @@ +package command + +import ( + "fmt" + + "github.com/pkg/errors" + "github.com/santhosh-tekuri/jsonschema/v5" + _ "github.com/santhosh-tekuri/jsonschema/v5/httploader" + "github.com/urfave/cli/v2" +) + +func Check() *cli.Command { + flags := []cli.Flag{} + + flags = append(flags, commonFlags()...) + + return &cli.Command{ + Name: "check", + Usage: "Check values with the given schema", + Flags: flags, + Action: func(ctx *cli.Context) error { + schema, err := loadSchema(ctx) + if err != nil { + return errors.Wrap(err, "could not load schema") + } + + _, values, err := loadData(ctx) + if err != nil { + return errors.Wrap(err, "could not load data") + } + + if err := schema.Validate(values); err != nil { + if _, ok := err.(*jsonschema.ValidationError); ok { + fmt.Printf("%#v\n", err) + + return errors.New("invalid values") + } + + return errors.Wrap(err, "could not validate values") + } + + if err := outputValues(ctx, values); err != nil { + return errors.Wrap(err, "could not output updated values") + } + + return nil + }, + } +} diff --git a/internal/command/check_test.go b/internal/command/check_test.go new file mode 100644 index 0000000..49f0e7b --- /dev/null +++ b/internal/command/check_test.go @@ -0,0 +1,87 @@ +package command + +import ( + "flag" + "testing" + + "github.com/pkg/errors" + "github.com/urfave/cli/v2" +) + +type ExpectFunc func(t *testing.T, cmd *cli.Command, err error) + +type checkCommandTestCase struct { + Name string + SchemaFile string + DefaultFile string + ValuesFile string + Expect ExpectFunc +} + +var checkCommandTestCases = []checkCommandTestCase{ + { + Name: "ok", + SchemaFile: "file://testdata/check/schema.json", + DefaultFile: "file://testdata/check/defaults.json", + ValuesFile: "file://testdata/check/values-ok.json", + Expect: expectNoError, + }, + { + Name: "nok", + SchemaFile: "file://testdata/check/schema.json", + DefaultFile: "file://testdata/check/defaults.json", + ValuesFile: "file://testdata/check/values-nok.json", + Expect: expectError, + }, +} + +func TestCheck(t *testing.T) { + t.Parallel() + + for _, tc := range checkCommandTestCases { + func(tc *checkCommandTestCase) { + t.Run(tc.Name, func(t *testing.T) { + t.Parallel() + + flags := flag.NewFlagSet("", flag.ExitOnError) + cmd := Check() + + for _, f := range cmd.Flags { + if err := f.Apply(flags); err != nil { + t.Fatal(errors.WithStack(err)) + } + } + + err := flags.Parse([]string{ + "check", + "--schema", tc.SchemaFile, + "--defaults", tc.DefaultFile, + "--values", tc.ValuesFile, + "--output", "null://local?format=json", + }) + if err != nil { + t.Fatal(errors.WithStack(err)) + } + + app := cli.NewApp() + ctx := cli.NewContext(app, flags, nil) + + err = cmd.Run(ctx) + + tc.Expect(t, cmd, err) + }) + }(&tc) + } +} + +func expectNoError(t *testing.T, cmd *cli.Command, err error) { + if err != nil { + t.Error(errors.Wrap(err, "the command result in an unexpected error")) + } +} + +func expectError(t *testing.T, cmd *cli.Command, err error) { + if err == nil { + t.Error(errors.New("an error should have been returned")) + } +} diff --git a/internal/command/common.go b/internal/command/common.go index 8713f95..5ce3643 100644 --- a/internal/command/common.go +++ b/internal/command/common.go @@ -5,6 +5,7 @@ import ( "io" "net/url" "os" + "reflect" encjson "encoding/json" @@ -20,6 +21,7 @@ import ( "forge.cadoles.com/wpetit/formidable/internal/data/updater/null" "forge.cadoles.com/wpetit/formidable/internal/data/updater/stdout" "forge.cadoles.com/wpetit/formidable/internal/def" + "forge.cadoles.com/wpetit/formidable/internal/merge" "github.com/pkg/errors" "github.com/santhosh-tekuri/jsonschema/v5" "github.com/urfave/cli/v2" @@ -113,6 +115,46 @@ func loadDefaults(ctx *cli.Context) (interface{}, error) { return defaults, nil } +func loadData(ctx *cli.Context) (defaults interface{}, values interface{}, err error) { + values, err = loadValues(ctx) + if err != nil { + return nil, nil, errors.Wrap(err, "could not load values") + } + + defaults, err = loadDefaults(ctx) + if err != nil { + return nil, nil, errors.Wrap(err, "could not load defaults") + } + + merged, err := getMatchingZeroValue(values) + if err != nil { + return nil, nil, errors.WithStack(err) + } + + if defaults != nil { + if err := merge.Merge(&merged, defaults, values); err != nil { + return nil, nil, errors.Wrap(err, "could not merge values") + } + + values = merged + } + + return defaults, values, nil +} + +func getMatchingZeroValue(values interface{}) (interface{}, error) { + valuesKind := reflect.TypeOf(values).Kind() + + switch valuesKind { + case reflect.Map: + return make(map[string]interface{}, 0), nil + case reflect.Slice: + return make([]interface{}, 0), nil + default: + return nil, errors.Errorf("unexpected type '%T'", values) + } +} + func loadSchema(ctx *cli.Context) (*jsonschema.Schema, error) { schemaFlag := ctx.String("schema") diff --git a/internal/command/edit.go b/internal/command/edit.go index e1b147c..6df6db4 100644 --- a/internal/command/edit.go +++ b/internal/command/edit.go @@ -55,14 +55,9 @@ func Edit() *cli.Command { return errors.Wrap(err, "could not load schema") } - values, err := loadValues(ctx) + defaults, values, err := loadData(ctx) if err != nil { - return errors.Wrap(err, "could not load values") - } - - defaults, err := loadDefaults(ctx) - if err != nil { - return errors.Wrap(err, "could not load defaults") + return errors.Wrap(err, "could not load data") } srvCtx, srvCancel := context.WithCancel(ctx.Context) diff --git a/internal/command/get.go b/internal/command/get.go index cb966fd..0e82817 100644 --- a/internal/command/get.go +++ b/internal/command/get.go @@ -26,9 +26,9 @@ func Get() *cli.Command { return errors.Wrap(err, "could not load schema") } - values, err := loadValues(ctx) + _, values, err := loadData(ctx) if err != nil { - return errors.Wrap(err, "could not load values") + return errors.Wrap(err, "could not load data") } if err := schema.Validate(values); err != nil { diff --git a/internal/command/root.go b/internal/command/root.go index 0cafced..86b65dd 100644 --- a/internal/command/root.go +++ b/internal/command/root.go @@ -8,5 +8,6 @@ func Root() []*cli.Command { Set(), Get(), Delete(), + Check(), } } diff --git a/internal/command/set.go b/internal/command/set.go index 7806f09..d16f0ca 100644 --- a/internal/command/set.go +++ b/internal/command/set.go @@ -33,9 +33,9 @@ func Set() *cli.Command { return errors.Wrap(err, "could not load schema") } - values, err := loadValues(ctx) + _, values, err := loadData(ctx) if err != nil { - return errors.Wrap(err, "could not load values") + return errors.Wrap(err, "could not load data") } rawPointer := ctx.Args().Get(0) diff --git a/internal/command/testdata/check/defaults.json b/internal/command/testdata/check/defaults.json new file mode 100644 index 0000000..536fcc5 --- /dev/null +++ b/internal/command/testdata/check/defaults.json @@ -0,0 +1,5 @@ +{ + "foo": { + "bar": "test" + } +} \ No newline at end of file diff --git a/internal/command/testdata/check/schema.json b/internal/command/testdata/check/schema.json new file mode 100644 index 0000000..a6f39f4 --- /dev/null +++ b/internal/command/testdata/check/schema.json @@ -0,0 +1,17 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema", + "type": "object", + "properties": { + "foo": { + "type": "object", + "properties": { + "bar": { + "type": "string" + } + }, + "required": ["bar"] + } + }, + "required": ["foo"], + "additionalProperties": true +} \ No newline at end of file diff --git a/internal/command/testdata/check/values-nok.json b/internal/command/testdata/check/values-nok.json new file mode 100644 index 0000000..1ae31ac --- /dev/null +++ b/internal/command/testdata/check/values-nok.json @@ -0,0 +1,5 @@ +{ + "foo": { + "bar": false + } +} \ No newline at end of file diff --git a/internal/command/testdata/check/values-ok.json b/internal/command/testdata/check/values-ok.json new file mode 100644 index 0000000..73cd85a --- /dev/null +++ b/internal/command/testdata/check/values-ok.json @@ -0,0 +1,3 @@ +{ + "test": 1 +} \ No newline at end of file diff --git a/internal/jsonpointer/delete_test.go b/internal/jsonpointer/delete_test.go index 7ba235e..88730fe 100644 --- a/internal/jsonpointer/delete_test.go +++ b/internal/jsonpointer/delete_test.go @@ -33,7 +33,12 @@ func TestPointerDelete(t *testing.T) { { "nestedObject": { "foo": [ - "bar" + "bar", + { + "prop1": { + "subProp": 1 + } + } ] } }`, @@ -45,7 +50,8 @@ func TestPointerDelete(t *testing.T) { { "nestedObject": { "foo": [ - "bar" + "bar", + 0 ] } }`, diff --git a/internal/jsonpointer/set_test.go b/internal/jsonpointer/set_test.go index 9043cbb..61ce556 100644 --- a/internal/jsonpointer/set_test.go +++ b/internal/jsonpointer/set_test.go @@ -14,7 +14,9 @@ import ( type pointerSetTestCase struct { DocPath string Pointer string + Force bool Value interface{} + ExpectedError error ExpectedRawDocument string } @@ -37,7 +39,12 @@ func TestPointerSet(t *testing.T) { "nestedObject": { "foo": [ "bar", - "test" + "test", + { + "prop1": { + "subProp": 1 + } + } ] } }`, @@ -52,11 +59,44 @@ func TestPointerSet(t *testing.T) { "foo": [ "bar", 0, + { + "prop1": { + "subProp": 1 + } + }, "baz" ] } }`, }, + { + DocPath: "./testdata/set/nested.json", + Pointer: "/nestedObject/foo/2/prop2", + Value: "baz", + Force: true, + ExpectedRawDocument: ` + { + "nestedObject": { + "foo": [ + "bar", + 0, + { + "prop2": "baz", + "prop1": { + "subProp": 1 + } + } + ] + } + }`, + }, + { + DocPath: "./testdata/set/nested.json", + Pointer: "/nestedObject/foo/2/prop2", + Value: "baz", + Force: false, + ExpectedError: ErrNotFound, + }, } for i, tc := range testCases { @@ -77,8 +117,19 @@ func TestPointerSet(t *testing.T) { pointer := New(tc.Pointer) - updatedDoc, err := pointer.Set(baseDoc, tc.Value) - if err != nil { + var updatedDoc interface{} + + if tc.Force { + updatedDoc, err = pointer.Force(baseDoc, tc.Value) + } else { + updatedDoc, err = pointer.Set(baseDoc, tc.Value) + } + + if tc.ExpectedError != nil && !errors.Is(err, tc.ExpectedError) { + t.Fatalf("Expected error '%v', got '%v'", tc.ExpectedError, errors.Cause(err)) + } + + if tc.ExpectedError == nil && err != nil { t.Fatal(errors.WithStack(err)) } @@ -89,12 +140,20 @@ func TestPointerSet(t *testing.T) { var expectedDoc interface{} + if tc.ExpectedRawDocument == "" { + return + } + if err := json.Unmarshal([]byte(tc.ExpectedRawDocument), &expectedDoc); err != nil { t.Fatal(errors.WithStack(err)) } if !reflect.DeepEqual(expectedDoc, updatedDoc) { - t.Errorf("Set pointer '%s' -> '%v': expected document '%s', got '%s'", tc.Pointer, tc.Value, strings.TrimSpace(tc.ExpectedRawDocument), rawDoc) + command := "Set" + if tc.Force { + command = "Force" + } + t.Errorf("%s pointer '%s' -> '%v': expected document '%s', got '%s'", command, tc.Pointer, tc.Value, strings.TrimSpace(tc.ExpectedRawDocument), rawDoc) } }) }(i, tc) diff --git a/internal/jsonpointer/testdata/set/nested.json b/internal/jsonpointer/testdata/set/nested.json index ee92d8f..d153850 100644 --- a/internal/jsonpointer/testdata/set/nested.json +++ b/internal/jsonpointer/testdata/set/nested.json @@ -2,7 +2,12 @@ "nestedObject": { "foo": [ "bar", - 0 + 0, + { + "prop1": { + "subProp": 1 + } + } ] } } \ No newline at end of file diff --git a/internal/merge/merge.go b/internal/merge/merge.go new file mode 100644 index 0000000..de30898 --- /dev/null +++ b/internal/merge/merge.go @@ -0,0 +1,91 @@ +package merge + +import ( + "reflect" + + "github.com/imdario/mergo" + "github.com/pkg/errors" +) + +var ( + ErrNonPointerDst = errors.New("dst is not a pointer") + ErrUnsupportedMerge = errors.New("unsupported merge") + ErrUnexpectedFailedCast = errors.New("unexpected failed cast") +) + +func Merge(dst interface{}, sources ...interface{}) error { + if reflect.TypeOf(dst).Kind() != reflect.Ptr { + return errors.WithStack(ErrNonPointerDst) + } + + dstPointedKind := reflect.Indirect(reflect.ValueOf(dst)).Elem().Kind() + + for _, src := range sources { + srcKind := reflect.ValueOf(src).Kind() + + switch dstPointedKind { + case reflect.Map: + if srcKind != dstPointedKind { + return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind)) + } + + if err := mergeMaps(dst, src); err != nil { + return errors.WithStack(err) + } + + case reflect.Slice: + if srcKind != dstPointedKind { + return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind)) + } + + if err := mergeSlices(dst, src); err != nil { + return errors.WithStack(err) + } + + default: + return errors.WithStack(unsupportedMergeError(dstPointedKind, srcKind)) + } + } + + return nil +} + +func unsupportedMergeError(dstKind reflect.Kind, defaultsKind reflect.Kind) error { + return errors.Wrapf(ErrUnsupportedMerge, "could not merge '%s' with defaults '%s'", dstKind, defaultsKind) +} + +func mergeMaps(dst interface{}, defaults interface{}) error { + dstMap, ok := reflect.Indirect(reflect.ValueOf(dst)).Elem().Interface().(map[string]interface{}) + if !ok { + return errors.WithStack(ErrUnexpectedFailedCast) + } + + defaultsMap, ok := defaults.(map[string]interface{}) + if !ok { + return errors.WithStack(ErrUnexpectedFailedCast) + } + + if err := mergo.Merge(&dstMap, defaultsMap, mergo.WithOverride); err != nil { + return errors.WithStack(err) + } + + return nil +} + +func mergeSlices(dst interface{}, defaults interface{}) error { + dstSlice, ok := reflect.Indirect(reflect.ValueOf(dst)).Elem().Interface().([]interface{}) + if !ok { + return errors.WithStack(ErrUnexpectedFailedCast) + } + + defaultsSlice, ok := defaults.([]interface{}) + if !ok { + return errors.WithStack(ErrUnexpectedFailedCast) + } + + if err := mergo.Merge(&dstSlice, defaultsSlice, mergo.WithOverride); err != nil { + return errors.WithStack(err) + } + + return nil +} diff --git a/internal/merge/merge_test.go b/internal/merge/merge_test.go new file mode 100644 index 0000000..4d63499 --- /dev/null +++ b/internal/merge/merge_test.go @@ -0,0 +1,69 @@ +package merge + +import ( + "reflect" + "testing" + + "github.com/davecgh/go-spew/spew" +) + +type mergeTestCase struct { + Name string + Dst interface{} + Dflts interface{} + ExpectedResult interface{} + ShouldFail bool +} + +var mergeTestCases = []mergeTestCase{ + { + Name: "simple-maps", + Dst: map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "test", + }, + }, + Dflts: map[string]interface{}{ + "other": true, + "foo": map[string]interface{}{ + "bar": true, + "baz": 1, + }, + }, + ExpectedResult: map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "test", + "baz": 1, + }, + "other": true, + }, + }, + { + Name: "string-slices", + Dst: []string{"foo"}, + Dflts: []string{"bar"}, + ExpectedResult: []string{"foo"}, + }, +} + +func TestMerge(t *testing.T) { + t.Parallel() + + for _, tc := range mergeTestCases { + func(tc *mergeTestCase) { + t.Run(tc.Name, func(t *testing.T) { + t.Parallel() + + err := Merge(&tc.Dst, tc.Dflts) + + if tc.ShouldFail && err == nil { + t.Error("merge should have failed") + } + + if !reflect.DeepEqual(tc.Dst, tc.ExpectedResult) { + t.Errorf("tc.Dst should have been the same as tc.ExpectedResult. Expected: %s, got %s", spew.Sdump(tc.ExpectedResult), spew.Sdump(tc.Dst)) + } + }) + }(&tc) + } +} diff --git a/internal/server/route.go b/internal/server/route.go index 131743d..82e37f8 100644 --- a/internal/server/route.go +++ b/internal/server/route.go @@ -49,7 +49,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) { if err := r.ParseForm(); err != nil { panic(errors.WithStack(err)) } else { - values, err = handleForm(r.Form, s.schema, values) + values, err = handleForm(r.Form, s.schema, s.values) if err != nil { panic(errors.WithStack(err)) } @@ -57,7 +57,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) { data.Values = values } - if err := s.schema.Validate(data.Values); err != nil { + if err := s.schema.Validate(values); err != nil { validationErr, ok := err.(*jsonschema.ValidationError) if !ok { panic(errors.Wrap(err, "could not validate values")) @@ -68,7 +68,7 @@ func (s *Server) handleFormReq(w http.ResponseWriter, r *http.Request) { if data.Error == nil { if s.onUpdate != nil { - if err := s.onUpdate(data.Values); err != nil { + if err := s.onUpdate(values); err != nil { panic(errors.Wrap(err, "could not update values")) } } diff --git a/internal/server/template/blocks/form_input_array.html.tmpl b/internal/server/template/blocks/form_input_array.html.tmpl index 52100a1..e8dd304 100644 --- a/internal/server/template/blocks/form_input_array.html.tmpl +++ b/internal/server/template/blocks/form_input_array.html.tmpl @@ -1,7 +1,7 @@ {{ define "form_input_array" }} {{ $root := . }} {{ $fullProperty := getFullProperty .Parent .Property }} - {{ $values := getValue .Defaults .Values $fullProperty }} + {{ $values := getValue .Values $fullProperty }} {{ range $index, $value := $values }} diff --git a/internal/server/template/blocks/form_input_boolean.html.tmpl b/internal/server/template/blocks/form_input_boolean.html.tmpl index b3924ef..818c6c3 100644 --- a/internal/server/template/blocks/form_input_boolean.html.tmpl +++ b/internal/server/template/blocks/form_input_boolean.html.tmpl @@ -1,6 +1,6 @@ {{define "form_input_boolean"}} {{ $fullProperty := getFullProperty .Parent .Property }} -{{ $checked := getValue .Defaults .Values $fullProperty }} +{{ $checked := getValue .Values $fullProperty }}