diff --git a/ffjsonnet.go b/ffjsonnet.go index 422b8b83aae464f29097a7575a2695ec43d29917..8a3bad030157e69b85ba3dd5db4a0ceaecfabc96 100644 --- a/ffjsonnet.go +++ b/ffjsonnet.go @@ -1,10 +1,12 @@ package ffjsonnet import ( + "encoding/json" "fmt" "io" + "strings" - "go.jolheiser.com/cuesonnet" + "github.com/google/go-jsonnet" ) // Parser is a helper function that uses a default ParseConfig. @@ -17,8 +19,6 @@ type ParseConfig struct { // Delimiter is used when concatenating nested node keys into a flag name. // The default delimiter is ".". Delimiter string - // Schema is a CUE schema to validate the incoming (JSON)net - Schema string } // Parse a document from the provided io.Reader, using the provided set @@ -28,14 +28,23 @@ func (pc *ParseConfig) Parse(r io.Reader, set func(name, value string) error) error { if pc.Delimiter == "" { pc.Delimiter = "." } - if pc.Schema == "" { - pc.Schema = "_" + + data, err := io.ReadAll(r) + if err != nil { + return err + } + + vm := jsonnet.MakeVM() + jsonData, err := vm.EvaluateAnonymousSnippet("config", string(data)) + if err != nil { + return err } - schema := cuesonnet.Schema(pc.Schema) + d := json.NewDecoder(strings.NewReader(jsonData)) + d.UseNumber() // required for stringifying values - var m map[string]any - if err := schema.Decode(r, &m); err != nil { + var m map[string]interface{} + if err := d.Decode(&m); err != nil { return ParseError{Inner: err} } diff --git a/ffjsonnet_test.go b/ffjsonnet_test.go index 7e6234cff11dea5cf132a971ed96ee8eee1e4116..50a76e249aba598ae01f5b74d1c9cf38948a799e 100644 --- a/ffjsonnet_test.go +++ b/ffjsonnet_test.go @@ -9,58 +9,9 @@ "github.com/peterbourgon/ff/v3/fftest" "go.jolheiser.com/ffjsonnet" ) -func TestSchema(t *testing.T) { - for _, testcase := range []struct { - name string - file string - schema string - want fftest.Vars - }{ - { - name: "valid schema", - file: "testdata/basic.json", - schema: "import \"time\"\n{ s: string, i: int, b: bool, d: time.Duration }", - want: fftest.Vars{S: "s", I: 10, B: true, D: 5 * time.Second}, - }, - { - name: "valid schema (jsonnet)", - file: "testdata/basic.jsonnet", - schema: "import \"time\"\n{ s: string, i: int, b: bool, d: time.Duration }", - want: fftest.Vars{S: "s", I: 10, B: true, D: 5 * time.Second}, - }, - { - name: "invalid schema constraint", - file: "testdata/basic.json", - schema: "i: >100", - want: fftest.Vars{WantParseErrorString: "i:"}, - }, - { - name: "invalid schema type", - file: "testdata/basic.json", - schema: "s: int", - want: fftest.Vars{WantParseErrorString: "s:"}, - }, - { - name: "invalid duration", - file: "testdata/bad_duration.json", - schema: "import \"time\"\n{ d: time.Duration }", - want: fftest.Vars{WantParseErrorString: "d:"}, - }, - } { - t.Run(testcase.name, func(t *testing.T) { - t.Parallel() - fs, vars := fftest.Pair() - pc := &ffjsonnet.ParseConfig{Schema: testcase.schema} - vars.ParseError = ff.Parse(fs, nil, - ff.WithConfigFile(testcase.file), - ff.WithConfigFileParser(pc.Parse), - ) - fftest.Compare(t, &testcase.want, vars) - }) - } -} +func TestJSONParser(t *testing.T) { + t.Parallel() -func TestJSONParser(t *testing.T) { for _, testcase := range []struct { name string args []string @@ -97,15 +48,8 @@ args: []string{}, file: "testdata/bad.json", want: fftest.Vars{WantParseErrorString: "end of file"}, }, - { - name: "invalid duration", - args: []string{}, - file: "testdata/bad_duration.json", - want: fftest.Vars{WantParseErrorString: "parse error"}, - }, } { t.Run(testcase.name, func(t *testing.T) { - t.Parallel() fs, vars := fftest.Pair() vars.ParseError = ff.Parse(fs, testcase.args, ff.WithConfigFile(testcase.file), diff --git a/go.mod b/go.mod index f02cf2d9e677f37ffa385692c045c64f884ea1ec..95f0e3296f2813d201374bc4569a5383a2908444 100644 --- a/go.mod +++ b/go.mod @@ -1,27 +1,13 @@ module go.jolheiser.com/ffjsonnet -go 1.25.0 +go 1.22.3 require ( + github.com/google/go-jsonnet v0.20.0 github.com/peterbourgon/ff/v3 v3.4.0 - go.jolheiser.com/cuesonnet v0.0.0-20260608154847-ad92adf766cc ) require ( - cuelang.org/go v0.16.1 // indirect - github.com/cockroachdb/apd/v3 v3.2.3 // indirect - github.com/emicklei/proto v1.14.3 // indirect - github.com/google/go-jsonnet v0.22.0 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/mitchellh/go-wordwrap v1.0.1 // indirect - github.com/pelletier/go-toml/v2 v2.3.1 // indirect - github.com/protocolbuffers/txtpbfmt v0.0.0-20260420112717-c39628bde8b5 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect - golang.org/x/crypto v0.52.0 // indirect - golang.org/x/net v0.55.0 // indirect - golang.org/x/sys v0.46.0 // indirect - golang.org/x/text v0.37.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - sigs.k8s.io/yaml v1.6.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + sigs.k8s.io/yaml v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 08fe3fcde02b064e56481d1984d44110133876c0..5e3bbf39a84788869a3244b924808923d0fdafcb 100644 --- a/go.sum +++ b/go.sum @@ -1,69 +1,12 @@ -cuelabs.dev/go/oci/ociregistry v0.0.0-20251212221603-3adeb8663819 h1:Zh+Ur3OsoWpvALHPLT45nOekHkgOt+IOfutBbPqM17I= -cuelabs.dev/go/oci/ociregistry v0.0.0-20251212221603-3adeb8663819/go.mod h1:WjmQxb+W6nVNCgj8nXrF24lIz95AHwnSl36tpjDZSU8= -cuelang.org/go v0.16.1 h1:iPN1lHZd2J0hjcr8hfq9PnIGk7VfPkKFfxH4de+m9sE= -cuelang.org/go v0.16.1/go.mod h1:/aW3967FeWC5Hc1cDrN4Z4ICVApdMi83wO5L3uF/1hM= -github.com/cockroachdb/apd/v3 v3.2.3 h1:4Zx+I3R35bFXMnltzmjP79i2cravE4jTRL6ps9Aux80= -github.com/cockroachdb/apd/v3 v3.2.3/go.mod h1:klXJcjp+FffLTHlhIG69tezTDvdP065naDsHzKhYSqc= -github.com/emicklei/proto v1.14.3 h1:zEhlzNkpP8kN6utonKMzlPfIvy82t5Kb9mufaJxSe1Q= -github.com/emicklei/proto v1.14.3/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN9yvjX0A= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/go-jsonnet v0.22.0 h1:o0bOAIE+9SIfRZ7FXQPuta0mHLLE0AwbY/L5GTH5CH8= -github.com/google/go-jsonnet v0.22.0/go.mod h1:pLhKpu0/ODjL2Zev4y+CmCoHKAgONT1gSLQyriuYh9w= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= -github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= -github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/pelletier/go-toml/v2 v2.3.1 h1:MYEvvGnQjeNkRF1qUuGolNtNExTDwct51yp7olPtrEc= -github.com/pelletier/go-toml/v2 v2.3.1/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= +github.com/google/go-jsonnet v0.20.0 h1:WG4TTSARuV7bSm4PMB4ohjxe33IHT5WVTrJSU33uT4g= +github.com/google/go-jsonnet v0.20.0/go.mod h1:VbgWF9JX7ztlv770x/TolZNGGFfiHEVx9G6ca2eUmeA= github.com/peterbourgon/ff/v3 v3.4.0 h1:QBvM/rizZM1cB0p0lGMdmR7HxZeI/ZrBWB4DqLkMUBc= github.com/peterbourgon/ff/v3 v3.4.0/go.mod h1:zjJVUhx+twciwfDl0zBcFzl4dW8axCRyXE/eKY9RztQ= -github.com/protocolbuffers/txtpbfmt v0.0.0-20260420112717-c39628bde8b5 h1:Mckui8l+Wqz2Ve7XQvsE8SbHNmDWu8NA7Xce5NFJ/kM= -github.com/protocolbuffers/txtpbfmt v0.0.0-20260420112717-c39628bde8b5/go.mod h1:JSbkp0BviKovYYt9XunS95M3mLPibE9bGg+Y95DsEEY= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= -github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -go.jolheiser.com/cuesonnet v0.0.0-20260608154847-ad92adf766cc h1:pYFHXKY2BOjdK6ag9yr3XTNMTvfovHeldtndZmuo4tg= -go.jolheiser.com/cuesonnet v0.0.0-20260608154847-ad92adf766cc/go.mod h1:Vbhj9tI/M7a/p32d/PD3v4FgsL5lQWrcxq8ckYZfYCc= -go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= -go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.52.0 h1:RMs7fP2rXdep0CftQlK8Uf+kibLm7qkCcradZWYz988= -golang.org/x/crypto v0.52.0/go.mod h1:1QgfPxDqh0T2M/elOJtp9RvuR95kVjir0e6/BvEmGbc= -golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= -golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= -golang.org/x/net v0.55.0 h1:bcvxaJn3e1U6InsFWt1JUq1aSjnRxLzT2rtD2KfkDF8= -golang.org/x/net v0.55.0/go.mod h1:L5U2KuzuOe1lY7Z+aWVIKK6qEeJXnXV9yzGA+WCHJww= -golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs= -golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q= -golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= -golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= -golang.org/x/sys v0.46.0 h1:noSf2Fq6F8DBgS+LysIkx7rIExoNHJsxOAtPp4rthXw= -golang.org/x/sys v0.46.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= -golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= -golang.org/x/tools v0.44.0 h1:UP4ajHPIcuMjT1GqzDWRlalUEoY+uzoZKnhOjbIPD2c= -golang.org/x/tools v0.44.0/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= -sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= diff --git a/testdata/bad_duration.json b/testdata/bad_duration.json deleted file mode 100644 index b6738ac519920e002bbe2a5ca3b14a90e1b2ddf2..0000000000000000000000000000000000000000 --- a/testdata/bad_duration.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "s": "s", - "i": 10, - "b": true, - "d": "notaduration" -}