diff --git a/go.mod b/go.mod index 6cc4dd2..6c9c079 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/DistroByte/molecule go 1.26.0 require ( - github.com/getkin/kin-openapi v0.133.0 + github.com/getkin/kin-openapi v0.135.0 github.com/go-chi/chi/v5 v5.2.5 github.com/google/uuid v1.6.0 github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6 @@ -36,13 +36,11 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.20 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect - github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect - github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 // indirect - github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 // indirect + github.com/oasdiff/yaml v0.0.9 // indirect + github.com/oasdiff/yaml3 v0.0.9 // indirect github.com/perimeterx/marshmallow v1.1.5 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect golang.org/x/sys v0.41.0 // indirect golang.org/x/text v0.34.0 // indirect ) diff --git a/go.sum b/go.sum index 9c4850f..3759739 100644 --- a/go.sum +++ b/go.sum @@ -5,11 +5,10 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= -github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= -github.com/getkin/kin-openapi v0.133.0 h1:pJdmNohVIJ97r4AUFtEXRXwESr8b0bD721u/Tz6k8PQ= -github.com/getkin/kin-openapi v0.133.0/go.mod h1:boAciF6cXk5FhPqe/NQeBTeenbjqU4LhWBf09ILVvWE= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= +github.com/getkin/kin-openapi v0.135.0 h1:751SjYfbiwqukYuVjwYEIKNfrSwS5YpA7DZnKSwQgtg= +github.com/getkin/kin-openapi v0.135.0/go.mod h1:6dd5FJl6RdX4usBtFBaQhk9q62Yb2J0Mk5IhUO/QqFI= github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug= github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= @@ -27,15 +26,10 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 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/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/cronexpr v1.1.2 h1:wG/ZYIKT+RT3QkOdgYc+xsKWVRgnxJ1OJtjjy84fJ9A= -github.com/hashicorp/cronexpr v1.1.2/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= github.com/hashicorp/cronexpr v1.1.3 h1:rl5IkxXN2m681EfivTlccqIryzYJSXRGRNa0xeG7NA4= github.com/hashicorp/cronexpr v1.1.3/go.mod h1:P4wA0KBl9C5q2hABiMO7cp6jcIg96CDh1Efb3g1PWA4= -github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -45,8 +39,6 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= -github.com/hashicorp/nomad/api v0.0.0-20250317133216-16bbdd983307 h1:dJVFZM5wiEc8XGGduWPyxa2i0NwbeeqTCoffSKXrBS0= -github.com/hashicorp/nomad/api v0.0.0-20250317133216-16bbdd983307/go.mod h1:svtxn6QnrQ69P23VvIWMR34tg3vmwLz4UdUzm1dSCgE= github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6 h1:QN/GwpGyiW8RdNcHGMA1xVnM8tJkAGNDR/BZ47XR+OU= github.com/hashicorp/nomad/api v0.0.0-20260220212019-daca79db0bd6/go.mod h1:KkLNLU0Nyfh5jWsFoF/PsmMbKpRIAoIV4lmQoJWgKCk= github.com/jedib0t/go-pretty/v6 v6.7.8 h1:BVYrDy5DPBA3Qn9ICT+PokP9cvCv1KaHv2i+Hc8sr5o= @@ -59,47 +51,35 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.20 h1:WcT52H91ZUAwy8+HUkdM3THM6gXqXuLJi9O3rjcQQaQ= github.com/mattn/go-runewidth v0.0.20/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= -github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= -github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw= github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 h1:G7ERwszslrBzRxj//JalHPu/3yz+De2J+4aLtSRlHiY= -github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037/go.mod h1:2bpvgLBZEtENV5scfDFEtB/5+1M4hkQhDQrccEJ/qGw= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 h1:bQx3WeLcUWy+RletIKwUIt4x3t8n2SxavmoclizMb8c= -github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= +github.com/oasdiff/yaml v0.0.9 h1:zQOvd2UKoozsSsAknnWoDJlSK4lC0mpmjfDsfqNwX48= +github.com/oasdiff/yaml v0.0.9/go.mod h1:8lvhgJG4xiKPj3HN5lDow4jZHPlx1i7dIwzkdAo6oAM= +github.com/oasdiff/yaml3 v0.0.9 h1:rWPrKccrdUm8J0F3sGuU+fuh9+1K/RdJlWF7O/9yw2g= +github.com/oasdiff/yaml3 v0.0.9/go.mod h1:y5+oSEHCPT/DGrS++Wc/479ERge0zTFxaF8PbGKcg2o= github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX50IvK2s= github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0= github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY= github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ= -github.com/shoenig/test v1.7.1 h1:UJcjSAI3aUKx52kfcfhblgyhZceouhvvs3OYdWgn+PY= -github.com/shoenig/test v1.7.1/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/shoenig/test v1.12.2 h1:ZVT8NeIUwGWpZcKaepPmFMoNQ3sVpxvqUh/MAqwFiJI= +github.com/shoenig/test v1.12.2/go.mod h1:UxJ6u/x2v/TNs/LoLxBNJRV9DiwBBKYxXSyczsBHFoI= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= @@ -109,12 +89,8 @@ github.com/woodsbury/decimal128 v1.3.0/go.mod h1:C5UTmyTjW3JftjUFzOVhC20BEQa2a4Z golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= -golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= -golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk= golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/callback.go b/vendor/github.com/getkin/kin-openapi/openapi3/callback.go index 31f4e4b..8ebba51 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/callback.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/callback.go @@ -2,7 +2,7 @@ package openapi3 import ( "context" - "sort" + "slices" ) // Callback is specified by OpenAPI/Swagger standard version 3. @@ -43,7 +43,7 @@ func (callback *Callback) Validate(ctx context.Context, opts ...ValidationOption for key := range callback.Map() { keys = append(keys, key) } - sort.Strings(keys) + slices.Sort(keys) for _, key := range keys { v := callback.Value(key) if err := v.Validate(ctx); err != nil { @@ -56,6 +56,6 @@ func (callback *Callback) Validate(ctx context.Context, opts ...ValidationOption // UnmarshalJSON sets Callbacks to a copy of data. func (callbacks *Callbacks) UnmarshalJSON(data []byte) (err error) { - *callbacks, _, err = unmarshalStringMapP[CallbackRef](data) + *callbacks, err = unmarshalStringMapP[CallbackRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/components.go b/vendor/github.com/getkin/kin-openapi/openapi3/components.go index 890671a..0d94112 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/components.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/components.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" "fmt" - "sort" + "slices" "github.com/go-openapi/jsonpointer" ) @@ -95,7 +95,6 @@ func (components *Components) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "schemas") delete(x.Extensions, "parameters") delete(x.Extensions, "headers") @@ -120,7 +119,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Schemas { schemas = append(schemas, name) } - sort.Strings(schemas) + slices.Sort(schemas) for _, k := range schemas { v := components.Schemas[k] if err = ValidateIdentifier(k); err != nil { @@ -135,7 +134,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Parameters { parameters = append(parameters, name) } - sort.Strings(parameters) + slices.Sort(parameters) for _, k := range parameters { v := components.Parameters[k] if err = ValidateIdentifier(k); err != nil { @@ -150,7 +149,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.RequestBodies { requestBodies = append(requestBodies, name) } - sort.Strings(requestBodies) + slices.Sort(requestBodies) for _, k := range requestBodies { v := components.RequestBodies[k] if err = ValidateIdentifier(k); err != nil { @@ -165,7 +164,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Responses { responses = append(responses, name) } - sort.Strings(responses) + slices.Sort(responses) for _, k := range responses { if err = ValidateIdentifier(k); err != nil { return fmt.Errorf("response %q: %w", k, err) @@ -180,7 +179,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Headers { headers = append(headers, name) } - sort.Strings(headers) + slices.Sort(headers) for _, k := range headers { v := components.Headers[k] if err = ValidateIdentifier(k); err != nil { @@ -195,7 +194,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.SecuritySchemes { securitySchemes = append(securitySchemes, name) } - sort.Strings(securitySchemes) + slices.Sort(securitySchemes) for _, k := range securitySchemes { v := components.SecuritySchemes[k] if err = ValidateIdentifier(k); err != nil { @@ -210,7 +209,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Examples { examples = append(examples, name) } - sort.Strings(examples) + slices.Sort(examples) for _, k := range examples { v := components.Examples[k] if err = ValidateIdentifier(k); err != nil { @@ -225,7 +224,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Links { links = append(links, name) } - sort.Strings(links) + slices.Sort(links) for _, k := range links { v := components.Links[k] if err = ValidateIdentifier(k); err != nil { @@ -240,7 +239,7 @@ func (components *Components) Validate(ctx context.Context, opts ...ValidationOp for name := range components.Callbacks { callbacks = append(callbacks, name) } - sort.Strings(callbacks) + slices.Sort(callbacks) for _, k := range callbacks { v := components.Callbacks[k] if err = ValidateIdentifier(k); err != nil { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/contact.go b/vendor/github.com/getkin/kin-openapi/openapi3/contact.go index 2ade3c6..269db2f 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/contact.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/contact.go @@ -52,7 +52,6 @@ func (contact *Contact) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "name") delete(x.Extensions, "url") delete(x.Extensions, "email") diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/content.go b/vendor/github.com/getkin/kin-openapi/openapi3/content.go index 73e301e..0a6624a 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/content.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/content.go @@ -2,7 +2,7 @@ package openapi3 import ( "context" - "sort" + "slices" "strings" ) @@ -113,7 +113,7 @@ func (content Content) Validate(ctx context.Context, opts ...ValidationOption) e for key := range content { keys = append(keys, key) } - sort.Strings(keys) + slices.Sort(keys) for _, k := range keys { v := content[k] if err := v.Validate(ctx); err != nil { @@ -125,6 +125,6 @@ func (content Content) Validate(ctx context.Context, opts ...ValidationOption) e // UnmarshalJSON sets Content to a copy of data. func (content *Content) UnmarshalJSON(data []byte) (err error) { - *content, _, err = unmarshalStringMapP[MediaType](data) + *content, err = unmarshalStringMapP[MediaType](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go b/vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go index 6934c17..ca215bc 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go @@ -11,8 +11,22 @@ type Discriminator struct { Extensions map[string]any `json:"-" yaml:"-"` Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` - PropertyName string `json:"propertyName" yaml:"propertyName"` // required - Mapping StringMap `json:"mapping,omitempty" yaml:"mapping,omitempty"` + PropertyName string `json:"propertyName" yaml:"propertyName"` // required + Mapping StringMap[MappingRef] `json:"mapping,omitempty" yaml:"mapping,omitempty"` +} + +// MappingRef is a ref to a Schema objects. Unlike SchemaRefs it is serialised +// as a plain string instead of an object with a $ref key, as such it also does +// not support extensions. +type MappingRef SchemaRef + +func (mr *MappingRef) UnmarshalText(data []byte) error { + mr.Ref = string(data) + return nil +} + +func (mr MappingRef) MarshalText() ([]byte, error) { + return []byte(mr.Ref), nil } // MarshalJSON returns the JSON encoding of Discriminator. @@ -46,7 +60,6 @@ func (discriminator *Discriminator) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "propertyName") delete(x.Extensions, "mapping") if len(x.Extensions) == 0 { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/encoding.go b/vendor/github.com/getkin/kin-openapi/openapi3/encoding.go index 113eb73..ae2cfae 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/encoding.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/encoding.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" "fmt" - "sort" + "slices" ) // Encoding is specified by OpenAPI/Swagger 3.0 standard. @@ -24,6 +24,15 @@ func NewEncoding() *Encoding { return &Encoding{} } +// Encodings is a map of encoding objects keyed by field name. +type Encodings map[string]*Encoding + +// UnmarshalJSON sets Encodings to a copy of data. +func (encodings *Encodings) UnmarshalJSON(data []byte) (err error) { + *encodings, err = unmarshalStringMapP[Encoding](data) + return +} + func (encoding *Encoding) WithHeader(name string, header *Header) *Encoding { return encoding.WithHeaderRef(name, &HeaderRef{ Value: header, @@ -82,7 +91,6 @@ func (encoding *Encoding) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "contentType") delete(x.Extensions, "headers") delete(x.Extensions, "style") @@ -122,7 +130,7 @@ func (encoding *Encoding) Validate(ctx context.Context, opts ...ValidationOption for k := range encoding.Headers { headers = append(headers, k) } - sort.Strings(headers) + slices.Sort(headers) for _, k := range headers { v := encoding.Headers[k] if err := ValidateIdentifier(k); err != nil { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/example.go b/vendor/github.com/getkin/kin-openapi/openapi3/example.go index 44d5777..22422c3 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/example.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/example.go @@ -60,7 +60,6 @@ func (example *Example) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "summary") delete(x.Extensions, "description") delete(x.Extensions, "value") @@ -88,6 +87,6 @@ func (example *Example) Validate(ctx context.Context, opts ...ValidationOption) // UnmarshalJSON sets Examples to a copy of data. func (examples *Examples) UnmarshalJSON(data []byte) (err error) { - *examples, _, err = unmarshalStringMapP[ExampleRef](data) + *examples, err = unmarshalStringMapP[ExampleRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/extension.go b/vendor/github.com/getkin/kin-openapi/openapi3/extension.go index ca86078..4240047 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/extension.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/extension.go @@ -3,7 +3,7 @@ package openapi3 import ( "context" "fmt" - "sort" + "slices" "strings" ) @@ -24,7 +24,7 @@ func validateExtensions(ctx context.Context, extensions map[string]any) error { } if len(unknowns) != 0 { - sort.Strings(unknowns) + slices.Sort(unknowns) return fmt.Errorf("extra sibling fields: %+v", unknowns) } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go b/vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go index 7ff435f..672dd91 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/external_docs.go @@ -50,7 +50,6 @@ func (e *ExternalDocs) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "description") delete(x.Extensions, "url") if len(x.Extensions) == 0 { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/header.go b/vendor/github.com/getkin/kin-openapi/openapi3/header.go index 6b23db5..a37bcc4 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/header.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/header.go @@ -97,6 +97,6 @@ func (header *Header) Validate(ctx context.Context, opts ...ValidationOption) er // UnmarshalJSON sets Headers to a copy of data. func (headers *Headers) UnmarshalJSON(data []byte) (err error) { - *headers, _, err = unmarshalStringMapP[HeaderRef](data) + *headers, err = unmarshalStringMapP[HeaderRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/helpers.go b/vendor/github.com/getkin/kin-openapi/openapi3/helpers.go index b36b0b7..e95f752 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/helpers.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/helpers.go @@ -6,7 +6,7 @@ import ( "path" "reflect" "regexp" - "sort" + "slices" "strings" "github.com/go-openapi/jsonpointer" @@ -70,7 +70,7 @@ func componentNames[E any](s map[string]E) []string { for i := range s { out = append(out, i) } - sort.Strings(out) + slices.Sort(out) return out } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/info.go b/vendor/github.com/getkin/kin-openapi/openapi3/info.go index ed5710e..fd6af3f 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/info.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/info.go @@ -63,7 +63,6 @@ func (info *Info) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "title") delete(x.Extensions, "description") delete(x.Extensions, "termsOfService") diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go b/vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go index b725baf..2398bc6 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/internalize_refs.go @@ -6,7 +6,7 @@ import ( "strings" ) -// RefNameResolver maps a component to an name that is used as it's internalized name. +// RefNameResolver maps a component to a name that is used as it's internalized name. // // The function should avoid name collisions (i.e. be a injective mapping). // It must only contain characters valid for fixed field names: [IdentifierRegExp]. @@ -345,6 +345,17 @@ func (doc *T) derefSchema(s *Schema, refNameResolver RefNameResolver, parentIsEx } } + // Discriminator mapping values are special cases since they are not full + // ref objects but are string references to schema objects. + if s.Discriminator != nil { + for k, mapRef := range s.Discriminator.Mapping { + s2 := (*SchemaRef)(&mapRef) + isExternal := doc.addSchemaToSpec(s2, refNameResolver, parentIsExternal) + doc.derefSchema(s2.Value, refNameResolver, isExternal || parentIsExternal) + s.Discriminator.Mapping[k] = MappingRef(*s2) + } + } + for _, name := range componentNames(s.Properties) { s2 := s.Properties[name] isExternal := doc.addSchemaToSpec(s2, refNameResolver, parentIsExternal) diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/license.go b/vendor/github.com/getkin/kin-openapi/openapi3/license.go index eb47fc3..755b5d9 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/license.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/license.go @@ -46,7 +46,6 @@ func (license *License) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "name") delete(x.Extensions, "url") if len(x.Extensions) == 0 { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/link.go b/vendor/github.com/getkin/kin-openapi/openapi3/link.go index c76cf44..72a2e7e 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/link.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/link.go @@ -68,7 +68,6 @@ func (link *Link) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "operationRef") delete(x.Extensions, "operationId") delete(x.Extensions, "description") @@ -98,6 +97,6 @@ func (link *Link) Validate(ctx context.Context, opts ...ValidationOption) error // UnmarshalJSON sets Links to a copy of data. func (links *Links) UnmarshalJSON(data []byte) (err error) { - *links, _, err = unmarshalStringMapP[LinkRef](data) + *links, err = unmarshalStringMapP[LinkRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/loader.go b/vendor/github.com/getkin/kin-openapi/openapi3/loader.go index 67674fc..f0a13e5 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/loader.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/loader.go @@ -15,9 +15,9 @@ import ( "strings" ) -// IncludeOrigin specifies whether to include the origin of the OpenAPI elements -// Set this to true before loading a spec to include the origin of the OpenAPI elements -// Note it is global and affects all loaders +// IncludeOrigin specifies whether to include the origin of the OpenAPI elements. +// Deprecated: set Loader.IncludeOrigin instead. This global is read by NewLoader +// for backward compatibility but is not safe for concurrent use. var IncludeOrigin = false func foundUnresolvedRef(ref string) error { @@ -33,6 +33,11 @@ type Loader struct { // IsExternalRefsAllowed enables visiting other files IsExternalRefsAllowed bool + // IncludeOrigin enables recording the file/line/column of each OpenAPI element. + // Prefer this over the package-level IncludeOrigin global, which is not safe for + // concurrent use. + IncludeOrigin bool + // ReadFromURIFunc allows overriding the any file/URL reading func ReadFromURIFunc ReadFromURIFunc @@ -53,7 +58,8 @@ type Loader struct { // NewLoader returns an empty Loader func NewLoader() *Loader { return &Loader{ - Context: context.Background(), + Context: context.Background(), + IncludeOrigin: IncludeOrigin, } } @@ -92,8 +98,13 @@ func (loader *Loader) allowsExternalRefs(ref string) (err error) { } func (loader *Loader) loadSingleElementFromURI(ref string, rootPath *url.URL, element any) (*url.URL, error) { - if err := loader.allowsExternalRefs(ref); err != nil { - return nil, err + // When a custom ReadFromURIFunc is installed, defer the external-ref decision to it; + // the function itself is responsible for enforcing any access policy. + // Otherwise enforce IsExternalRefsAllowed here before attempting any I/O. + if loader.ReadFromURIFunc == nil { + if err := loader.allowsExternalRefs(ref); err != nil { + return nil, err + } } resolvedPath, err := resolvePathWithRef(ref, rootPath) @@ -108,7 +119,7 @@ func (loader *Loader) loadSingleElementFromURI(ref string, rootPath *url.URL, el if err != nil { return nil, err } - if err := unmarshal(data, element, IncludeOrigin); err != nil { + if err := unmarshal(data, element, loader.IncludeOrigin, resolvedPath); err != nil { return nil, err } @@ -144,7 +155,7 @@ func (loader *Loader) LoadFromIoReader(reader io.Reader) (*T, error) { func (loader *Loader) LoadFromData(data []byte) (*T, error) { loader.resetVisitedPathItemRefs() doc := &T{} - if err := unmarshal(data, doc, IncludeOrigin); err != nil { + if err := unmarshal(data, doc, loader.IncludeOrigin, nil); err != nil { return nil, err } if err := loader.ResolveRefsIn(doc, nil); err != nil { @@ -173,7 +184,7 @@ func (loader *Loader) loadFromDataWithPathInternal(data []byte, location *url.UR doc := &T{} loader.visitedDocuments[uri] = doc - if err := unmarshal(data, doc, IncludeOrigin); err != nil { + if err := unmarshal(data, doc, loader.IncludeOrigin, location); err != nil { return nil, err } @@ -306,8 +317,11 @@ func (loader *Loader) resolveRefPath(ref string, path *url.URL) (*url.URL, error return path, nil } - if err := loader.allowsExternalRefs(ref); err != nil { - return nil, err + // When a custom ReadFromURIFunc is installed, defer the external-ref decision to it. + if loader.ReadFromURIFunc == nil { + if err := loader.allowsExternalRefs(ref); err != nil { + return nil, err + } } resolvedPath, err := resolvePathWithRef(ref, path) @@ -427,7 +441,7 @@ func (loader *Loader) resolveComponent(doc *T, ref string, path *url.URL, resolv if err2 != nil { return nil, nil, err } - if err2 = unmarshal(data, &cursor, IncludeOrigin); err2 != nil { + if err2 = unmarshal(data, &cursor, loader.IncludeOrigin, path); err2 != nil { return nil, nil, err } if cursor, err2 = drill(cursor); err2 != nil || cursor == nil { @@ -970,6 +984,22 @@ func (loader *Loader) resolveSchemaRef(doc *T, component *SchemaRef, documentPat return err } } + // Discriminator mapping refs are a special case since they are not full + // ref objects but are plain strings that reference schema objects. + // Only resolve refs that look like external references (contain a path). + // Plain schema names like "Dog" or internal refs like "#/components/schemas/Dog" + // don't need to be resolved by the loader. + if value.Discriminator != nil { + for k, v := range value.Discriminator.Mapping { + // Only resolve if it looks like an external ref (contains path separator) + if strings.Contains(v.Ref, "/") && !strings.HasPrefix(v.Ref, "#") { + if err := loader.resolveSchemaRef(doc, (*SchemaRef)(&v), documentPath, visited); err != nil { + return err + } + value.Discriminator.Mapping[k] = v + } + } + } return nil } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/maplike.go b/vendor/github.com/getkin/kin-openapi/openapi3/maplike.go index 36aa244..5a26ae5 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/maplike.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/maplike.go @@ -2,7 +2,7 @@ package openapi3 import ( "encoding/json" - "sort" + "slices" "strings" "github.com/go-openapi/jsonpointer" @@ -110,7 +110,7 @@ func (responses *Responses) UnmarshalJSON(data []byte) (err error) { for k := range m { ks = append(ks, k) } - sort.Strings(ks) + slices.Sort(ks) x := Responses{ Extensions: make(map[string]any), @@ -124,17 +124,6 @@ func (responses *Responses) UnmarshalJSON(data []byte) (err error) { continue } - if k == originKey { - var data []byte - if data, err = json.Marshal(v); err != nil { - return - } - if err = json.Unmarshal(data, &x.Origin); err != nil { - return - } - continue - } - var data []byte if data, err = json.Marshal(v); err != nil { return @@ -251,7 +240,7 @@ func (callback *Callback) UnmarshalJSON(data []byte) (err error) { for k := range m { ks = append(ks, k) } - sort.Strings(ks) + slices.Sort(ks) x := Callback{ Extensions: make(map[string]any), @@ -265,17 +254,6 @@ func (callback *Callback) UnmarshalJSON(data []byte) (err error) { continue } - if k == originKey { - var data []byte - if data, err = json.Marshal(v); err != nil { - return - } - if err = json.Unmarshal(data, &x.Origin); err != nil { - return - } - continue - } - var data []byte if data, err = json.Marshal(v); err != nil { return @@ -392,7 +370,7 @@ func (paths *Paths) UnmarshalJSON(data []byte) (err error) { for k := range m { ks = append(ks, k) } - sort.Strings(ks) + slices.Sort(ks) x := Paths{ Extensions: make(map[string]any), @@ -406,17 +384,6 @@ func (paths *Paths) UnmarshalJSON(data []byte) (err error) { continue } - if k == originKey { - var data []byte - if data, err = json.Marshal(v); err != nil { - return - } - if err = json.Unmarshal(data, &x.Origin); err != nil { - return - } - continue - } - var data []byte if data, err = json.Marshal(v); err != nil { return diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/marsh.go b/vendor/github.com/getkin/kin-openapi/openapi3/marsh.go index 2f00828..a549070 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/marsh.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/marsh.go @@ -3,6 +3,7 @@ package openapi3 import ( "encoding/json" "fmt" + "net/url" "strings" "github.com/oasdiff/yaml" @@ -16,7 +17,7 @@ func unmarshalError(jsonUnmarshalErr error) error { return jsonUnmarshalErr } -func unmarshal(data []byte, v any, includeOrigin bool) error { +func unmarshal(data []byte, v any, includeOrigin bool, location *url.URL) error { var jsonErr, yamlErr error // See https://github.com/getkin/kin-openapi/issues/680 @@ -25,8 +26,15 @@ func unmarshal(data []byte, v any, includeOrigin bool) error { } // UnmarshalStrict(data, v) TODO: investigate how ymlv3 handles duplicate map keys - if yamlErr = yaml.UnmarshalWithOrigin(data, v, includeOrigin); yamlErr == nil { + var file string + if location != nil { + file = location.String() + } + if tree, err := yaml.UnmarshalWithOriginTree(data, v, yaml.OriginOpt{Enabled: includeOrigin, File: file}); err == nil { + applyOrigins(v, tree) return nil + } else { + yamlErr = err } // If both unmarshaling attempts fail, return a new error that includes both errors diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go b/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go index 576826f..5be2284 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "sort" + "slices" "github.com/go-openapi/jsonpointer" ) @@ -16,10 +16,10 @@ type MediaType struct { Extensions map[string]any `json:"-" yaml:"-"` Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` - Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"` - Example any `json:"example,omitempty" yaml:"example,omitempty"` - Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"` - Encoding map[string]*Encoding `json:"encoding,omitempty" yaml:"encoding,omitempty"` + Schema *SchemaRef `json:"schema,omitempty" yaml:"schema,omitempty"` + Example any `json:"example,omitempty" yaml:"example,omitempty"` + Examples Examples `json:"examples,omitempty" yaml:"examples,omitempty"` + Encoding Encodings `json:"encoding,omitempty" yaml:"encoding,omitempty"` } var _ jsonpointer.JSONPointable = (*MediaType)(nil) @@ -57,7 +57,7 @@ func (mediaType *MediaType) WithExample(name string, value any) *MediaType { func (mediaType *MediaType) WithEncoding(name string, enc *Encoding) *MediaType { encoding := mediaType.Encoding if encoding == nil { - encoding = make(map[string]*Encoding) + encoding = make(Encodings) mediaType.Encoding = encoding } encoding[name] = enc @@ -102,7 +102,6 @@ func (mediaType *MediaType) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "schema") delete(x.Extensions, "example") delete(x.Extensions, "examples") @@ -142,7 +141,7 @@ func (mediaType *MediaType) Validate(ctx context.Context, opts ...ValidationOpti for name := range examples { names = append(names, name) } - sort.Strings(names) + slices.Sort(names) for _, k := range names { v := examples[k] if err := v.Validate(ctx); err != nil { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go b/vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go index ef1592e..ed8a016 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/openapi3.go @@ -26,6 +26,12 @@ type T struct { visited visitedComponent url *url.URL + + // Document-scoped format validators + // These validators are automatically used by all schemas in this document + stringFormats map[string]StringFormatValidator + numberFormats map[string]NumberFormatValidator + integerFormats map[string]IntegerFormatValidator } var _ jsonpointer.JSONPointable = (*T)(nil) @@ -137,6 +143,64 @@ func (doc *T) AddServers(servers ...*Server) { doc.Servers = append(doc.Servers, servers...) } +// SetStringFormatValidators sets document-scoped string format validators. +// These validators are automatically used by all schemas in this document. +func (doc *T) SetStringFormatValidators(validators map[string]StringFormatValidator) { + doc.stringFormats = validators +} + +// SetStringFormatValidator sets a single document-scoped string format validator. +func (doc *T) SetStringFormatValidator(name string, validator StringFormatValidator) { + if doc.stringFormats == nil { + doc.stringFormats = make(map[string]StringFormatValidator) + } + doc.stringFormats[name] = validator +} + +// SetNumberFormatValidators sets document-scoped number format validators. +// These validators are automatically used by all schemas in this document. +func (doc *T) SetNumberFormatValidators(validators map[string]NumberFormatValidator) { + doc.numberFormats = validators +} + +// SetNumberFormatValidator sets a single document-scoped number format validator. +func (doc *T) SetNumberFormatValidator(name string, validator NumberFormatValidator) { + if doc.numberFormats == nil { + doc.numberFormats = make(map[string]NumberFormatValidator) + } + doc.numberFormats[name] = validator +} + +// SetIntegerFormatValidators sets document-scoped integer format validators. +// These validators are automatically used by all schemas in this document. +func (doc *T) SetIntegerFormatValidators(validators map[string]IntegerFormatValidator) { + doc.integerFormats = validators +} + +// SetIntegerFormatValidator sets a single document-scoped integer format validator. +func (doc *T) SetIntegerFormatValidator(name string, validator IntegerFormatValidator) { + if doc.integerFormats == nil { + doc.integerFormats = make(map[string]IntegerFormatValidator) + } + doc.integerFormats[name] = validator +} + +// GetSchemaValidationOptions returns SchemaValidationOptions that include +// this document's format validators. Use this when validating schemas from this document. +func (doc *T) GetSchemaValidationOptions() []SchemaValidationOption { + var opts []SchemaValidationOption + if doc.stringFormats != nil { + opts = append(opts, WithStringFormatValidators(doc.stringFormats)) + } + if doc.numberFormats != nil { + opts = append(opts, WithNumberFormatValidators(doc.numberFormats)) + } + if doc.integerFormats != nil { + opts = append(opts, WithIntegerFormatValidators(doc.integerFormats)) + } + return opts +} + // Validate returns an error if T does not comply with the OpenAPI spec. // Validations Options can be provided to modify the validation behavior. func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error { @@ -203,3 +267,11 @@ func (doc *T) Validate(ctx context.Context, opts ...ValidationOption) error { return validateExtensions(ctx, doc.Extensions) } + +// ValidateSchemaJSON validates data against a schema using this document's format validators. +// This is a convenience method that automatically applies the document's format validators. +func (doc *T) ValidateSchemaJSON(schema *Schema, value any, opts ...SchemaValidationOption) error { + // Combine document's validators with any additional options + allOpts := append(doc.GetSchemaValidationOptions(), opts...) + return schema.VisitJSON(value, allOpts...) +} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/operation.go b/vendor/github.com/getkin/kin-openapi/openapi3/operation.go index f32836e..c26e260 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/operation.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/operation.go @@ -117,7 +117,6 @@ func (operation *Operation) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "tags") delete(x.Extensions, "summary") delete(x.Extensions, "description") diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/origin.go b/vendor/github.com/getkin/kin-openapi/openapi3/origin.go index d2a51d9..12170ce 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/origin.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/origin.go @@ -1,17 +1,256 @@ package openapi3 +import ( + "reflect" + "strings" + + "github.com/oasdiff/yaml" +) + const originKey = "__origin__" +var originPtrType = reflect.TypeFor[*Origin]() + // Origin contains the origin of a collection. // Key is the location of the collection itself. -// Fields is a map of the location of each field in the collection. +// Fields is a map of the location of each scalar field in the collection. +// Sequences is a map of the location of each item in sequence-valued fields. type Origin struct { - Key *Location `json:"key,omitempty" yaml:"key,omitempty"` - Fields map[string]Location `json:"fields,omitempty" yaml:"fields,omitempty"` + Key *Location `json:"key,omitempty" yaml:"key,omitempty"` + Fields map[string]Location `json:"fields,omitempty" yaml:"fields,omitempty"` + Sequences map[string][]Location `json:"sequences,omitempty" yaml:"sequences,omitempty"` } // Location is a struct that contains the location of a field. type Location struct { - Line int `json:"line,omitempty" yaml:"line,omitempty"` - Column int `json:"column,omitempty" yaml:"column,omitempty"` + File string `json:"file,omitempty" yaml:"file,omitempty"` + Line int `json:"line,omitempty" yaml:"line,omitempty"` + Column int `json:"column,omitempty" yaml:"column,omitempty"` + Name string `json:"name,omitempty" yaml:"name,omitempty"` +} + +// originFromSeq parses the compact []any sequence produced by yaml3's addOrigin. +// +// Format: [file, key_name, key_line, key_col, nf, f1_name, f1_delta, f1_col, ..., ns, s1_name, s1_count, s1_l0_delta, s1_c0, ...] +func originFromSeq(s []any) *Origin { + // Need at least: file, key_name, key_line, key_col, nf, ns + if len(s) < 6 { + return nil + } + file, _ := s[0].(string) + keyName, _ := s[1].(string) + keyLine := toInt(s[2]) + keyCol := toInt(s[3]) + + o := &Origin{ + Key: &Location{ + File: file, + Line: keyLine, + Column: keyCol, + Name: keyName, + }, + } + + idx := 4 + nf := toInt(s[idx]) + idx++ + if nf > 0 && idx+nf*3 <= len(s) { + o.Fields = make(map[string]Location, nf) + for range nf { + fname, _ := s[idx].(string) + delta := toInt(s[idx+1]) + col := toInt(s[idx+2]) + o.Fields[fname] = Location{ + File: file, + Line: keyLine + delta, + Column: col, + Name: fname, + } + idx += 3 + } + } + + if idx >= len(s) { + return o + } + ns := toInt(s[idx]) + idx++ + if ns > 0 { + o.Sequences = make(map[string][]Location, ns) + for range ns { + if idx >= len(s) { + break + } + sname, _ := s[idx].(string) + idx++ + if idx >= len(s) { + break + } + count := toInt(s[idx]) + idx++ + locs := make([]Location, count) + for j := 0; j < count && idx+2 < len(s); j++ { + name, _ := s[idx].(string) + delta := toInt(s[idx+1]) + col := toInt(s[idx+2]) + locs[j] = Location{File: file, Line: keyLine + delta, Column: col, Name: name} + idx += 3 + } + o.Sequences[sname] = locs + } + } + return o +} + +// toInt converts numeric types to int. Handles int/uint64 from YAML decoding. +func toInt(v any) int { + switch n := v.(type) { + case int: + return n + case uint64: + return int(n) + } + return 0 +} + +// applyOrigins walks a Go struct tree and a parallel OriginTree, setting +// Origin fields on each struct from the extracted origin data. +func applyOrigins(v any, tree *yaml.OriginTree) { + if tree == nil { + return + } + applyOriginsToValue(reflect.ValueOf(v), tree) +} + +func applyOriginsToValue(val reflect.Value, tree *yaml.OriginTree) { + // Keep track of the last pointer so we can pass it to struct handlers + // (needed for calling methods like Map() on maplike types). + var ptr reflect.Value + for val.Kind() == reflect.Pointer || val.Kind() == reflect.Interface { + if val.IsNil() { + return + } + if val.Kind() == reflect.Pointer { + ptr = val + } + val = val.Elem() + } + + switch val.Kind() { + case reflect.Struct: + applyOriginsToStruct(val, ptr, tree) + case reflect.Map: + applyOriginsToMap(val, tree) + case reflect.Slice: + applyOriginsToSlice(val, tree) + } +} + +func applyOriginsToStruct(val reflect.Value, ptr reflect.Value, tree *yaml.OriginTree) { + typ := val.Type() + + // Set Origin field for structs whose Origin field has an __origin__ json tag (most types) + // or a "-" json tag (Response). Skip *Ref types whose Origin has no json tag. + if tree.Origin != nil { + if sf, ok := typ.FieldByName("Origin"); ok && sf.Type == originPtrType { + tag := sf.Tag.Get("json") + if strings.Contains(tag, originKey) || tag == "-" { + if s, ok := tree.Origin.([]any); ok { + val.FieldByName("Origin").Set(reflect.ValueOf(originFromSeq(s))) + } + } + } + } + + // Recurse into exported struct fields using json tags + for i := 0; i < typ.NumField(); i++ { + sf := typ.Field(i) + if !sf.IsExported() { + continue + } + tag := jsonTagName(sf) + if tag == "" || tag == "-" { + continue + } + childTree := tree.Fields[tag] + if childTree != nil { + applyOriginsToValue(val.Field(i), childTree) + } + } + + // Handle wrapper types whose inner struct has no json tag: + // - *Ref types (e.g. SchemaRef, ResponseRef) have a "Value" field + // - AdditionalProperties has a "Schema" field + // The origin tree data applies to the inner struct, not a sub-key. + for _, fieldName := range []string{"Value", "Schema"} { + vf := val.FieldByName(fieldName) + if !vf.IsValid() || vf.Kind() != reflect.Pointer || vf.IsNil() { + continue + } + sf, _ := typ.FieldByName(fieldName) + if sf.Tag.Get("json") == "" { + applyOriginsToValue(vf, tree) + } + } + + // Handle "maplike" types (Paths, Responses, Callback) whose items are + // stored in an unexported map accessible via a Map() method. + // Use the original pointer (if available) since dereferenced values + // are not addressable. + receiver := val + if ptr.IsValid() { + receiver = ptr + } else if val.CanAddr() { + receiver = val.Addr() + } + if receiver.Kind() == reflect.Pointer { + if mapMethod := receiver.MethodByName("Map"); mapMethod.IsValid() { + results := mapMethod.Call(nil) + if len(results) == 1 { + applyOriginsToMap(results[0], tree) + } + } + } +} + +func applyOriginsToMap(val reflect.Value, tree *yaml.OriginTree) { + if tree.Fields == nil { + return + } + for _, key := range val.MapKeys() { + childTree := tree.Fields[key.String()] + if childTree == nil { + continue + } + elem := val.MapIndex(key) + // Map values are not addressable. For pointer-typed values we can + // recurse directly. For value types we must copy, apply, and set back. + if elem.Kind() == reflect.Pointer || elem.Kind() == reflect.Interface { + applyOriginsToValue(elem, childTree) + } else if elem.Kind() == reflect.Struct { + // Copy to a settable value + cp := reflect.New(elem.Type()).Elem() + cp.Set(elem) + applyOriginsToStruct(cp, reflect.Value{}, childTree) + val.SetMapIndex(key, cp) + } + } +} + +func applyOriginsToSlice(val reflect.Value, tree *yaml.OriginTree) { + for i := 0; i < val.Len() && i < len(tree.Items); i++ { + if tree.Items[i] != nil { + applyOriginsToValue(val.Index(i), tree.Items[i]) + } + } +} + +// jsonTagName returns the JSON field name from a struct field's json tag. +func jsonTagName(f reflect.StructField) string { + tag := f.Tag.Get("json") + if tag == "" { + return "" + } + name, _, _ := strings.Cut(tag, ",") + return name } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go b/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go index 23582f7..6114563 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go @@ -5,7 +5,7 @@ import ( "encoding/json" "errors" "fmt" - "sort" + "slices" "strconv" "github.com/go-openapi/jsonpointer" @@ -217,7 +217,6 @@ func (parameter *Parameter) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "name") delete(x.Extensions, "in") delete(x.Extensions, "description") @@ -401,7 +400,7 @@ func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOpti for name := range examples { names = append(names, name) } - sort.Strings(names) + slices.Sort(names) for _, k := range names { v := examples[k] if err := v.Validate(ctx); err != nil { @@ -419,6 +418,6 @@ func (parameter *Parameter) Validate(ctx context.Context, opts ...ValidationOpti // UnmarshalJSON sets ParametersMap to a copy of data. func (parametersMap *ParametersMap) UnmarshalJSON(data []byte) (err error) { - *parametersMap, _, err = unmarshalStringMapP[ParameterRef](data) + *parametersMap, err = unmarshalStringMapP[ParameterRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/path_item.go b/vendor/github.com/getkin/kin-openapi/openapi3/path_item.go index 9839786..098e039 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/path_item.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/path_item.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" "net/http" - "sort" + "slices" ) // PathItem is specified by OpenAPI/Swagger standard version 3. @@ -99,7 +99,6 @@ func (pathItem *PathItem) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "$ref") delete(x.Extensions, "summary") delete(x.Extensions, "description") @@ -213,7 +212,7 @@ func (pathItem *PathItem) Validate(ctx context.Context, opts ...ValidationOption for method := range operations { methods = append(methods, method) } - sort.Strings(methods) + slices.Sort(methods) for _, method := range methods { operation := operations[method] if err := operation.Validate(ctx); err != nil { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/paths.go b/vendor/github.com/getkin/kin-openapi/openapi3/paths.go index edd8c87..844fb69 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/paths.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/paths.go @@ -1,9 +1,10 @@ package openapi3 import ( + "cmp" "context" "fmt" - "sort" + "slices" "strings" ) @@ -47,7 +48,7 @@ func (paths *Paths) Validate(ctx context.Context, opts ...ValidationOption) erro for key := range paths.Map() { keys = append(keys, key) } - sort.Strings(keys) + slices.Sort(keys) for _, path := range keys { pathItem := paths.Value(path) if path == "" || path[0] != '/' { @@ -78,7 +79,7 @@ func (paths *Paths) Validate(ctx context.Context, opts ...ValidationOption) erro for method := range operations { methods = append(methods, method) } - sort.Strings(methods) + slices.Sort(methods) for _, method := range methods { operation := operations[method] var setParams []string @@ -159,7 +160,7 @@ func (paths *Paths) InMatchingOrder() []string { ordered := make([]string, 0, paths.Len()) for c := 0; c <= max; c++ { if ps, ok := vars[c]; ok { - sort.Sort(sort.Reverse(sort.StringSlice(ps))) + slices.SortFunc(ps, func(a, b string) int { return cmp.Compare(b, a) }) ordered = append(ordered, ps...) } } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/ref.go b/vendor/github.com/getkin/kin-openapi/openapi3/ref.go index 83893b6..2be1a2d 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/ref.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/ref.go @@ -1,10 +1,43 @@ package openapi3 +import ( + "context" + "encoding/json" +) + //go:generate go run refsgenerator.go // Ref is specified by OpenAPI/Swagger 3.0 standard. // See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#reference-object type Ref struct { - Ref string `json:"$ref" yaml:"$ref"` - Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` + Ref string `json:"$ref" yaml:"$ref"` + Extensions map[string]any `json:"-" yaml:"-"` + Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` +} + +// MarshalYAML returns the YAML encoding of Ref. +func (x Ref) MarshalYAML() (any, error) { + m := make(map[string]any, 1+len(x.Extensions)) + for k, v := range x.Extensions { + m[k] = v + } + if x := x.Ref; x != "" { + m["$ref"] = x + } + return m, nil +} + +// MarshalJSON returns the JSON encoding of Ref. +func (x Ref) MarshalJSON() ([]byte, error) { + y, err := x.MarshalYAML() + if err != nil { + return nil, err + } + return json.Marshal(y) +} + +// Validate returns an error if Extensions does not comply with the OpenAPI spec. +func (e *Ref) Validate(ctx context.Context, opts ...ValidationOption) error { + ctx = WithValidationOptions(ctx, opts...) + return validateExtensions(ctx, e.Extensions) } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/refs.go b/vendor/github.com/getkin/kin-openapi/openapi3/refs.go index fc11164..45ddae3 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/refs.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/refs.go @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" "net/url" - "sort" + "slices" "strings" "github.com/go-openapi/jsonpointer" @@ -54,7 +54,7 @@ func (x *CallbackRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of CallbackRef. func (x CallbackRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -79,7 +79,7 @@ func (x *CallbackRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -192,7 +192,7 @@ func (x *ExampleRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of ExampleRef. func (x ExampleRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -217,7 +217,7 @@ func (x *ExampleRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -330,7 +330,7 @@ func (x *HeaderRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of HeaderRef. func (x HeaderRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -355,7 +355,7 @@ func (x *HeaderRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -468,7 +468,7 @@ func (x *LinkRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of LinkRef. func (x LinkRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -493,7 +493,7 @@ func (x *LinkRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -606,7 +606,7 @@ func (x *ParameterRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of ParameterRef. func (x ParameterRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -631,7 +631,7 @@ func (x *ParameterRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -744,7 +744,7 @@ func (x *RequestBodyRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of RequestBodyRef. func (x RequestBodyRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -769,7 +769,7 @@ func (x *RequestBodyRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -882,7 +882,7 @@ func (x *ResponseRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of ResponseRef. func (x ResponseRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -907,7 +907,7 @@ func (x *ResponseRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -1020,7 +1020,7 @@ func (x *SchemaRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of SchemaRef. func (x SchemaRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -1045,7 +1045,7 @@ func (x *SchemaRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) @@ -1158,7 +1158,7 @@ func (x *SecuritySchemeRef) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of SecuritySchemeRef. func (x SecuritySchemeRef) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -1183,7 +1183,7 @@ func (x *SecuritySchemeRef) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl b/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl index 028deba..6e8d1d6 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl +++ b/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl @@ -6,7 +6,7 @@ import ( "encoding/json" "fmt" "net/url" - "sort" + "slices" "strings" "github.com/go-openapi/jsonpointer" @@ -54,7 +54,7 @@ func (x *{{ $type.Name }}Ref) setRefPath(u *url.URL) { // MarshalYAML returns the YAML encoding of {{ $type.Name }}Ref. func (x {{ $type.Name }}Ref) MarshalYAML() (any, error) { if ref := x.Ref; ref != "" { - return &Ref{Ref: ref}, nil + return &Ref{Ref: ref, Extensions: x.Extensions}, nil } return x.Value.MarshalYAML() } @@ -79,7 +79,7 @@ func (x *{{ $type.Name }}Ref) UnmarshalJSON(data []byte) error { for key := range extra { x.extra = append(x.extra, key) } - sort.Strings(x.extra) + slices.Sort(x.extra) for k := range extra { if !strings.HasPrefix(k, "x-") { delete(extra, k) diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl b/vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl index 634fccf..a11e176 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl +++ b/vendor/github.com/getkin/kin-openapi/openapi3/refs_test.tmpl @@ -12,6 +12,7 @@ import ( {{ range $type := .Types }} func Test{{ $type.Name }}Ref_Extensions(t *testing.T) { data := []byte(`{"$ref":"#/components/schemas/Pet","something":"integer","x-order":1}`) + expectMarshalJson := []byte(`{"$ref":"#/components/schemas/Pet","x-order":1}`) ref := {{ $type.Name }}Ref{} err := json.Unmarshal(data, &ref) @@ -34,6 +35,12 @@ func Test{{ $type.Name }}Ref_Extensions(t *testing.T) { err = ref.Validate(context.Background(), AllowExtraSiblingFields("something")) assert.ErrorContains(t, err, "found unresolved ref") // expected since value not defined + // Verify round trip JSON + // Compare as string to make error message more readable if different + outJson, err := ref.MarshalJSON() + assert.NoError(t, err) + assert.Equal(t, string(outJson), string(expectMarshalJson), "MarshalJSON output is not the same as input data") + // non-extension not json lookable _, err = ref.JSONLookup("something") assert.Error(t, err) diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/request_body.go b/vendor/github.com/getkin/kin-openapi/openapi3/request_body.go index 6c15ba0..f95e31b 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/request_body.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/request_body.go @@ -109,7 +109,6 @@ func (requestBody *RequestBody) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "description") delete(x.Extensions, "required") delete(x.Extensions, "content") @@ -141,6 +140,6 @@ func (requestBody *RequestBody) Validate(ctx context.Context, opts ...Validation // UnmarshalJSON sets RequestBodies to a copy of data. func (requestBodies *RequestBodies) UnmarshalJSON(data []byte) (err error) { - *requestBodies, _, err = unmarshalStringMapP[RequestBodyRef](data) + *requestBodies, err = unmarshalStringMapP[RequestBodyRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/response.go b/vendor/github.com/getkin/kin-openapi/openapi3/response.go index b87324a..d73d9be 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/response.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/response.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" "errors" - "sort" + "slices" "strconv" ) @@ -88,7 +88,7 @@ func (responses *Responses) Validate(ctx context.Context, opts ...ValidationOpti for key := range responses.Map() { keys = append(keys, key) } - sort.Strings(keys) + slices.Sort(keys) for _, key := range keys { v := responses.Value(key) if err := v.Validate(ctx); err != nil { @@ -173,7 +173,6 @@ func (response *Response) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "description") delete(x.Extensions, "headers") delete(x.Extensions, "content") @@ -206,7 +205,7 @@ func (response *Response) Validate(ctx context.Context, opts ...ValidationOption for name := range response.Headers { headers = append(headers, name) } - sort.Strings(headers) + slices.Sort(headers) for _, name := range headers { header := response.Headers[name] if err := header.Validate(ctx); err != nil { @@ -218,7 +217,7 @@ func (response *Response) Validate(ctx context.Context, opts ...ValidationOption for name := range response.Links { links = append(links, name) } - sort.Strings(links) + slices.Sort(links) for _, name := range links { link := response.Links[name] if err := link.Validate(ctx); err != nil { @@ -231,6 +230,6 @@ func (response *Response) Validate(ctx context.Context, opts ...ValidationOption // UnmarshalJSON sets ResponseBodies to a copy of data. func (responseBodies *ResponseBodies) UnmarshalJSON(data []byte) (err error) { - *responseBodies, _, err = unmarshalStringMapP[ResponseRef](data) + *responseBodies, err = unmarshalStringMapP[ResponseRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/schema.go b/vendor/github.com/getkin/kin-openapi/openapi3/schema.go index d76bef4..c551a80 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/schema.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/schema.go @@ -9,7 +9,7 @@ import ( "math" "math/big" "reflect" - "sort" + "slices" "strconv" "strings" "sync" @@ -413,7 +413,6 @@ func (schema *Schema) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "oneOf") delete(x.Extensions, "anyOf") delete(x.Extensions, "allOf") @@ -1051,7 +1050,7 @@ func (schema *Schema) validate(ctx context.Context, stack []*Schema) ([]*Schema, for name := range schema.Properties { properties = append(properties, name) } - sort.Strings(properties) + slices.Sort(properties) for _, name := range properties { ref := schema.Properties[name] v := ref.Value @@ -1299,7 +1298,7 @@ func (schema *Schema) visitNotOperation(settings *schemaValidationSettings, valu func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, value any) (err error, run bool) { var visitedOneOf, visitedAnyOf, visitedAllOf bool if v := schema.OneOf; len(v) > 0 { - var discriminatorRef string + var discriminatorRef MappingRef if schema.Discriminator != nil { pn := schema.Discriminator.PropertyName if valuemap, okcheck := value.(map[string]any); okcheck { @@ -1345,7 +1344,7 @@ func (schema *Schema) visitXOFOperations(settings *schemaValidationSettings, val return foundUnresolvedRef(item.Ref), false } - if discriminatorRef != "" && discriminatorRef != item.Ref { + if discriminatorRef.Ref != "" && discriminatorRef.Ref != item.Ref { continue } @@ -1527,7 +1526,12 @@ func (schema *Schema) visitJSONNumber(settings *schemaValidationSettings, value format := schema.Format if format != "" { if requireInteger { - if f, ok := SchemaIntegerFormats[format]; ok { + // Check per-validation validators first, then fall back to global + f, ok := settings.integerFormats[format] + if !ok { + f, ok = SchemaIntegerFormats[format] + } + if ok { if err := f.Validate(int64(value)); err != nil { var reason string schemaErr := &SchemaError{} @@ -1541,7 +1545,12 @@ func (schema *Schema) visitJSONNumber(settings *schemaValidationSettings, value } } } else { - if f, ok := SchemaNumberFormats[format]; ok { + // Check per-validation validators first, then fall back to global + f, ok := settings.numberFormats[format] + if !ok { + f, ok = SchemaNumberFormats[format] + } + if ok { if err := f.Validate(value); err != nil { var reason string schemaErr := &SchemaError{} @@ -1767,7 +1776,12 @@ func (schema *Schema) visitJSONString(settings *schemaValidationSettings, value var formatStrErr string var formatErr error if format := schema.Format; format != "" { - if f, ok := SchemaStringFormats[format]; ok { + // Check per-validation validators first, then fall back to global + f, ok := settings.stringFormats[format] + if !ok { + f, ok = SchemaStringFormats[format] + } + if ok { if err := f.Validate(value); err != nil { var reason string schemaErr := &SchemaError{} @@ -1920,7 +1934,7 @@ func (schema *Schema) visitJSONObject(settings *schemaValidationSettings, value for propName := range schema.Properties { properties = append(properties, propName) } - sort.Strings(properties) + slices.Sort(properties) for _, propName := range properties { propSchema := schema.Properties[propName] reqRO := settings.asreq && propSchema.Value.ReadOnly && !settings.readOnlyValidationDisabled @@ -1992,7 +2006,7 @@ func (schema *Schema) visitJSONObject(settings *schemaValidationSettings, value for k := range value { keys = append(keys, k) } - sort.Strings(keys) + slices.Sort(keys) for _, k := range keys { v := value[k] if properties != nil { @@ -2144,6 +2158,9 @@ func markSchemaErrorKey(err error, key string) error { if me, ok := unwrapped.(multiErrorForOneOf); ok { _ = markSchemaErrorKey(MultiError(me), key) } + if me, ok := unwrapped.(multiErrorForAllOf); ok { + _ = markSchemaErrorKey(MultiError(me), key) + } } } return v @@ -2257,6 +2274,6 @@ func unsupportedFormat(format string) error { // UnmarshalJSON sets Schemas to a copy of data. func (schemas *Schemas) UnmarshalJSON(data []byte) (err error) { - *schemas, _, err = unmarshalStringMapP[SchemaRef](data) + *schemas, err = unmarshalStringMapP[SchemaRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go b/vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go index 489105b..da954dc 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/schema_formats.go @@ -44,7 +44,7 @@ const ( FormatOfStringDate = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])$` // FormatOfStringDateTime is a RFC3339 date-time format regexp, for example "2017-07-21T17:32:28Z". - FormatOfStringDateTime = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])T([0-1][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})?$` + FormatOfStringDateTime = `^[0-9]{4}-(0[1-9]|10|11|12)-(0[1-9]|[12][0-9]|3[01])T([0-1][0-9]|2[0-3]):[0-5][0-9]:([0-5][0-9]|60)(\.[0-9]+)?(Z|(\+|-)[0-9]{2}:[0-9]{2})$` ) func init() { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go b/vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go index e9c1422..9d70a61 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/schema_validation_settings.go @@ -28,6 +28,11 @@ type schemaValidationSettings struct { defaultsSet func() customizeMessageError func(err *SchemaError) string + + // Per-validation format validators (checked before global ones) + stringFormats map[string]StringFormatValidator + numberFormats map[string]NumberFormatValidator + integerFormats map[string]IntegerFormatValidator } // FailFast returns schema validation errors quicker. @@ -83,6 +88,69 @@ func SetSchemaRegexCompiler(c RegexCompilerFunc) SchemaValidationOption { return func(s *schemaValidationSettings) { s.regexCompiler = c } } +// WithStringFormatValidators adds per-validation string format validators. +// These validators are checked before global SchemaStringFormats and allow +// different validations for the same format name across different specs. +func WithStringFormatValidators(validators map[string]StringFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + s.stringFormats = validators + } +} + +// WithStringFormatValidator adds a single per-validation string format validator. +// This validator is checked before global SchemaStringFormats and allows +// different validations for the same format name across different specs. +func WithStringFormatValidator(name string, validator StringFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + if s.stringFormats == nil { + s.stringFormats = make(map[string]StringFormatValidator) + } + s.stringFormats[name] = validator + } +} + +// WithNumberFormatValidators adds per-validation number format validators. +// These validators are checked before global SchemaNumberFormats and allow +// different validations for the same format name across different specs. +func WithNumberFormatValidators(validators map[string]NumberFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + s.numberFormats = validators + } +} + +// WithNumberFormatValidator adds a single per-validation number format validator. +// This validator is checked before global SchemaNumberFormats and allows +// different validations for the same format name across different specs. +func WithNumberFormatValidator(name string, validator NumberFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + if s.numberFormats == nil { + s.numberFormats = make(map[string]NumberFormatValidator) + } + s.numberFormats[name] = validator + } +} + +// WithIntegerFormatValidators adds per-validation integer format validators. +// These validators are checked before global SchemaIntegerFormats and allow +// different validations for the same format name across different specs. +func WithIntegerFormatValidators(validators map[string]IntegerFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + s.integerFormats = validators + } +} + +// WithIntegerFormatValidator adds a single per-validation integer format validator. +// This validator is checked before global SchemaIntegerFormats and allows +// different validations for the same format name across different specs. +func WithIntegerFormatValidator(name string, validator IntegerFormatValidator) SchemaValidationOption { + return func(s *schemaValidationSettings) { + if s.integerFormats == nil { + s.integerFormats = make(map[string]IntegerFormatValidator) + } + s.integerFormats[name] = validator + } +} + func newSchemaValidationSettings(opts ...SchemaValidationOption) *schemaValidationSettings { settings := &schemaValidationSettings{} for _, opt := range opts { diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go b/vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go index 6af80e8..d5310d8 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/security_requirements.go @@ -52,6 +52,6 @@ func (security *SecurityRequirement) Validate(ctx context.Context, opts ...Valid // UnmarshalJSON sets SecurityRequirement to a copy of data. func (security *SecurityRequirement) UnmarshalJSON(data []byte) (err error) { - *security, _, err = unmarshalStringMap[[]string](data) + *security, err = unmarshalStringMap[[]string](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go b/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go index 676002a..df09bd4 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go @@ -101,7 +101,6 @@ func (ss *SecurityScheme) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "type") delete(x.Extensions, "description") delete(x.Extensions, "name") @@ -273,7 +272,6 @@ func (flows *OAuthFlows) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "implicit") delete(x.Extensions, "password") delete(x.Extensions, "clientCredentials") @@ -322,10 +320,10 @@ type OAuthFlow struct { Extensions map[string]any `json:"-" yaml:"-"` Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` - AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"` - TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"` - RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"` - Scopes StringMap `json:"scopes" yaml:"scopes"` // required + AuthorizationURL string `json:"authorizationUrl,omitempty" yaml:"authorizationUrl,omitempty"` + TokenURL string `json:"tokenUrl,omitempty" yaml:"tokenUrl,omitempty"` + RefreshURL string `json:"refreshUrl,omitempty" yaml:"refreshUrl,omitempty"` + Scopes StringMap[string] `json:"scopes" yaml:"scopes"` // required } // MarshalJSON returns the JSON encoding of OAuthFlow. @@ -365,7 +363,6 @@ func (flow *OAuthFlow) UnmarshalJSON(data []byte) error { } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "authorizationUrl") delete(x.Extensions, "tokenUrl") delete(x.Extensions, "refreshUrl") @@ -437,6 +434,6 @@ func (flow *OAuthFlow) validate(ctx context.Context, typ oAuthFlowType, opts ... // UnmarshalJSON sets SecuritySchemes to a copy of data. func (securitySchemes *SecuritySchemes) UnmarshalJSON(data []byte) (err error) { - *securitySchemes, _, err = unmarshalStringMapP[SecuritySchemeRef](data) + *securitySchemes, err = unmarshalStringMapP[SecuritySchemeRef](data) return } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/server.go b/vendor/github.com/getkin/kin-openapi/openapi3/server.go index ea77517..81384c1 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/server.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/server.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" "net/url" - "sort" + "slices" "strings" ) @@ -53,9 +53,9 @@ type Server struct { Extensions map[string]any `json:"-" yaml:"-"` Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` - URL string `json:"url" yaml:"url"` // Required - Description string `json:"description,omitempty" yaml:"description,omitempty"` - Variables map[string]*ServerVariable `json:"variables,omitempty" yaml:"variables,omitempty"` + URL string `json:"url" yaml:"url"` // Required + Description string `json:"description,omitempty" yaml:"description,omitempty"` + Variables ServerVariables `json:"variables,omitempty" yaml:"variables,omitempty"` } // BasePath returns the base path extracted from the default values of variables, if any. @@ -115,7 +115,6 @@ func (server *Server) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "url") delete(x.Extensions, "description") delete(x.Extensions, "variables") @@ -218,7 +217,7 @@ func (server *Server) Validate(ctx context.Context, opts ...ValidationOption) (e for name := range server.Variables { variables = append(variables, name) } - sort.Strings(variables) + slices.Sort(variables) for _, name := range variables { v := server.Variables[name] if !strings.Contains(server.URL, "{"+name+"}") { @@ -234,6 +233,15 @@ func (server *Server) Validate(ctx context.Context, opts ...ValidationOption) (e // ServerVariable is specified by OpenAPI/Swagger standard version 3. // See https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#server-variable-object +// ServerVariables is a map of ServerVariable objects keyed by variable name. +type ServerVariables map[string]*ServerVariable + +// UnmarshalJSON sets ServerVariables to a copy of data. +func (serverVariables *ServerVariables) UnmarshalJSON(data []byte) (err error) { + *serverVariables, err = unmarshalStringMapP[ServerVariable](data) + return +} + type ServerVariable struct { Extensions map[string]any `json:"-" yaml:"-"` Origin *Origin `json:"__origin__,omitempty" yaml:"__origin__,omitempty"` @@ -278,7 +286,6 @@ func (serverVariable *ServerVariable) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "enum") delete(x.Extensions, "default") delete(x.Extensions, "description") diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go b/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go index d1b91ac..5cd68a5 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go @@ -3,60 +3,50 @@ package openapi3 import "encoding/json" // StringMap is a map[string]string that ignores the origin in the underlying json representation. -type StringMap map[string]string +type StringMap[V any] map[string]V // UnmarshalJSON sets StringMap to a copy of data. -func (stringMap *StringMap) UnmarshalJSON(data []byte) (err error) { - *stringMap, _, err = unmarshalStringMap[string](data) +func (stringMap *StringMap[V]) UnmarshalJSON(data []byte) (err error) { + *stringMap, err = unmarshalStringMap[V](data) return } // unmarshalStringMapP unmarshals given json into a map[string]*V -func unmarshalStringMapP[V any](data []byte) (map[string]*V, *Origin, error) { +func unmarshalStringMapP[V any](data []byte) (map[string]*V, error) { var m map[string]any if err := json.Unmarshal(data, &m); err != nil { - return nil, nil, err - } - - origin, err := popOrigin(m, originKey) - if err != nil { - return nil, nil, err + return nil, err } result := make(map[string]*V, len(m)) for k, v := range m { value, err := deepCast[V](v) if err != nil { - return nil, nil, err + return nil, err } result[k] = value } - return result, origin, nil + return result, nil } // unmarshalStringMap unmarshals given json into a map[string]V -func unmarshalStringMap[V any](data []byte) (map[string]V, *Origin, error) { +func unmarshalStringMap[V any](data []byte) (map[string]V, error) { var m map[string]any if err := json.Unmarshal(data, &m); err != nil { - return nil, nil, err - } - - origin, err := popOrigin(m, originKey) - if err != nil { - return nil, nil, err + return nil, err } result := make(map[string]V, len(m)) for k, v := range m { value, err := deepCast[V](v) if err != nil { - return nil, nil, err + return nil, err } result[k] = *value } - return result, origin, nil + return result, nil } // deepCast casts any value to a value of type V. @@ -72,17 +62,3 @@ func deepCast[V any](value any) (*V, error) { } return &result, nil } - -// popOrigin removes the origin from the map and returns it. -func popOrigin(m map[string]any, key string) (*Origin, error) { - if !IncludeOrigin { - return nil, nil - } - - origin, err := deepCast[Origin](m[key]) - if err != nil { - return nil, err - } - delete(m, key) - return origin, nil -} diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/tag.go b/vendor/github.com/getkin/kin-openapi/openapi3/tag.go index 841161e..f5d6acc 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/tag.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/tag.go @@ -76,7 +76,6 @@ func (t *Tag) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "name") delete(x.Extensions, "description") delete(x.Extensions, "externalDocs") diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/xml.go b/vendor/github.com/getkin/kin-openapi/openapi3/xml.go index e960249..4719c8f 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/xml.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/xml.go @@ -59,7 +59,6 @@ func (xml *XML) UnmarshalJSON(data []byte) error { return unmarshalError(err) } _ = json.Unmarshal(data, &x.Extensions) - delete(x.Extensions, originKey) delete(x.Extensions, "name") delete(x.Extensions, "namespace") delete(x.Extensions, "prefix") diff --git a/vendor/github.com/oasdiff/yaml/README.md b/vendor/github.com/oasdiff/yaml/README.md index bdb0187..4507d74 100644 --- a/vendor/github.com/oasdiff/yaml/README.md +++ b/vendor/github.com/oasdiff/yaml/README.md @@ -6,9 +6,19 @@ ![Latest Tag](https://img.shields.io/github/v/tag/invopop/yaml) ## Fork -This fork is an improved version of the invopop/yaml package, designed to include line and column location information for YAML elements during unmarshalling. -To include location information use ```UnmarshalWithOrigin``` instead of ```Unmarshal```. -The heavy lifting is done by the underlying [oasdiff/yaml3](https://github.com/oasdiff/yaml3) package. +This fork is an improved version of the invopop/yaml package, designed to include line and column location information for YAML elements during unmarshalling. + +Origin tracking uses a two-pass approach: +1. `UnmarshalWithOriginTree` decodes the YAML and extracts `__origin__` metadata injected by the underlying [oasdiff/yaml3](https://github.com/oasdiff/yaml3) decoder, returning an `*OriginTree` alongside the decoded struct. +2. The caller walks the `OriginTree` to apply file/line/column information to the decoded Go structs. + +To decode without origin tracking, use `Unmarshal` as usual. To decode with origin tracking: + +```go +tree, err := yaml.UnmarshalWithOriginTree(data, &v, yaml.OriginOpt{Enabled: true, File: "myfile.yaml"}) +``` + +The returned `*OriginTree` mirrors the YAML document structure. Each node holds a compact `[]any` sequence with the file, key name, line, column, and locations of scalar fields and sequence items within that mapping. When `Enabled` is false, `nil` is returned for the tree with no overhead. ## Introduction diff --git a/vendor/github.com/oasdiff/yaml/yaml.go b/vendor/github.com/oasdiff/yaml/yaml.go index c49678e..d71ee20 100644 --- a/vendor/github.com/oasdiff/yaml/yaml.go +++ b/vendor/github.com/oasdiff/yaml/yaml.go @@ -16,7 +16,7 @@ import ( "reflect" "strconv" - "github.com/oasdiff/yaml3" + yaml "github.com/oasdiff/yaml3" ) // Marshal the object into JSON then converts JSON to YAML and returns the @@ -38,36 +38,159 @@ func Marshal(o interface{}) ([]byte, error) { // JSONOpt is a decoding option for decoding from JSON format. type JSONOpt func(*json.Decoder) *json.Decoder -// YAMLOpt is a decoding option for decoding from YAML format. -type YAMLOpt func(*yaml.Decoder) *yaml.Decoder - // Unmarshal converts YAML to JSON then uses JSON to unmarshal into an object, // optionally configuring the behavior of the JSON unmarshal. func Unmarshal(y []byte, o interface{}, opts ...JSONOpt) error { - return UnmarshalWithOrigin(y, o, false, opts...) + _, err := UnmarshalWithOriginTree(y, o, OriginOpt{}, opts...) + return err } -// UnmarshalWithOrigin is like Unmarshal but if withOrigin is true, it will -// include the origin information in the output. -func UnmarshalWithOrigin(y []byte, o interface{}, withOrigin bool, opts ...JSONOpt) error { - dec := yaml.NewDecoder(bytes.NewReader(y)) - dec.Origin(withOrigin) - return unmarshal(dec, o, opts) +// OriginOpt controls origin-tracking behavior in UnmarshalWithOriginTree. +type OriginOpt struct { + // Enabled adds __origin__ metadata to maps during unmarshaling. + Enabled bool + // File is the source file name recorded in origin metadata. + File string } -func unmarshal(dec *yaml.Decoder, o interface{}, opts []JSONOpt) error { +// OriginTree holds __origin__ data extracted from a YAML-decoded map tree. +// It mirrors the structure of the spec: Fields tracks map children by key, +// Items tracks slice children by index. +type OriginTree struct { + // File is the source file for all origins in this subtree. + // Set once at the root of each decode call; all nodes in the same + // decode share the same file. + File string + // Origin is the raw __origin__ value ([]any compact sequence) for this node. + // Format: [key_name, key_line, key_col, nf, f1_name, f1_delta, f1_col, ..., ns, ...] + Origin any + // Fields holds child trees keyed by map key name. + Fields map[string]*OriginTree + // Items holds child trees for slice elements (index-aligned). + Items []*OriginTree +} + +// UnmarshalWithOriginTree is like UnmarshalWithOrigin but strips __origin__ +// from the intermediate map before JSON conversion and returns the extracted +// origin data as an OriginTree. The caller can apply the tree to Go structs +// after unmarshaling. When origin tracking is disabled, the returned tree is nil. +func UnmarshalWithOriginTree(y []byte, o interface{}, origin OriginOpt, opts ...JSONOpt) (*OriginTree, error) { + dec := yaml.NewDecoder(bytes.NewReader(y)) + dec.Origin(origin.Enabled, origin.File) + + // Decode YAML into a generic object. + var yamlObj interface{} + if err := dec.Decode(&yamlObj); err != nil { + if !errors.Is(err, io.EOF) { + return nil, fmt.Errorf("error converting YAML to JSON: %v", err) + } + } + + // Extract __origin__ before JSON conversion so the JSON stays small. + var tree *OriginTree + if origin.Enabled { + tree = extractOrigins(yamlObj, origin.File) + } + + // Convert to JSON (without __origin__) and unmarshal into the target struct. vo := reflect.ValueOf(o) - j, err := yamlToJSON(dec, &vo) + jsonObj, err := convertToJSONableObject(yamlObj, &vo) if err != nil { - return fmt.Errorf("error converting YAML to JSON: %v", err) + return nil, fmt.Errorf("error converting YAML to JSON: %v", err) } - - err = jsonUnmarshal(bytes.NewReader(j), o, opts...) + j, err := json.Marshal(jsonObj) if err != nil { - return fmt.Errorf("error unmarshaling JSON: %v", err) + return nil, fmt.Errorf("error converting YAML to JSON: %v", err) + } + if err := jsonUnmarshal(bytes.NewReader(j), o, opts...); err != nil { + return nil, fmt.Errorf("error unmarshaling JSON: %v", err) } - return nil + return tree, nil +} + +const originKey = "__origin__" + +// extractOrigins recursively extracts and removes __origin__ entries from a +// YAML-decoded map tree, returning the origin data as an OriginTree. +// file is the source file for all nodes in this decode call. +func extractOrigins(v any, file string) *OriginTree { + switch val := v.(type) { + case map[string]any: + return extractOriginsFromStringMap(val, file) + case map[interface{}]interface{}: + // yaml3 produces map[interface{}]interface{} when map keys are non-string + // (e.g. integer HTTP status codes like 200). __origin__ is always a string + // key, so we must handle this case to strip it from mixed-key maps. + tree := &OriginTree{File: file} + if orig, ok := val[originKey]; ok { + tree.Origin = orig + delete(val, originKey) + } + for k, child := range val { + if childTree := extractOrigins(child, file); childTree != nil { + if tree.Fields == nil { + tree.Fields = make(map[string]*OriginTree) + } + // Convert key to string: mirrors convertToJSONableObject behaviour. + // String keys pass through; int/int64/float64 keys are formatted. + var ks string + switch kt := k.(type) { + case string: + ks = kt + case int: + ks = strconv.Itoa(kt) + case int64: + ks = strconv.FormatInt(kt, 10) + case float64: + ks = strconv.FormatFloat(kt, 'g', -1, 64) + default: + ks = fmt.Sprintf("%v", k) + } + tree.Fields[ks] = childTree + } + } + if tree.Origin == nil && tree.Fields == nil { + return nil + } + return tree + case []any: + var items []*OriginTree + hasChild := false + for _, child := range val { + childTree := extractOrigins(child, file) + items = append(items, childTree) // may be nil; preserves index alignment + if childTree != nil { + hasChild = true + } + } + if !hasChild { + return nil + } + return &OriginTree{File: file, Items: items} + default: + return nil + } +} + +func extractOriginsFromStringMap(val map[string]any, file string) *OriginTree { + tree := &OriginTree{File: file} + if orig, ok := val[originKey]; ok { + tree.Origin = orig + delete(val, originKey) + } + for k, child := range val { + if childTree := extractOrigins(child, file); childTree != nil { + if tree.Fields == nil { + tree.Fields = make(map[string]*OriginTree) + } + tree.Fields[k] = childTree + } + } + if tree.Origin == nil && tree.Fields == nil { + return nil + } + return tree } // jsonUnmarshal unmarshals the JSON byte stream from the given reader into the @@ -142,6 +265,7 @@ func yamlToJSON(dec *yaml.Decoder, jsonTarget *reflect.Value) ([]byte, error) { return json.Marshal(jsonObj) } +// convertToJSONableObject converts a YAML object to a JSON-compatible object. func convertToJSONableObject(yamlObj interface{}, jsonTarget *reflect.Value) (interface{}, error) { //nolint:gocyclo var err error diff --git a/vendor/github.com/oasdiff/yaml3/README.md b/vendor/github.com/oasdiff/yaml3/README.md index f08ebf4..3a218f2 100644 --- a/vendor/github.com/oasdiff/yaml3/README.md +++ b/vendor/github.com/oasdiff/yaml3/README.md @@ -2,7 +2,24 @@ Fork ---- -This fork is an improved version of the go-yaml/yaml package, designed to include line and column location information for YAML elements during unmarshalling. +This fork is an improved version of the go-yaml/yaml package, enhanced to inject `__origin__` metadata into YAML mapping nodes during decoding, recording the file, line, and column of each key. + +To enable origin tracking, call `Origin` on the decoder before decoding: + +```go +dec := yaml.NewDecoder(r) +dec.Origin(true, "myfile.yaml") + +var v interface{} +dec.Decode(&v) +// Each decoded map now contains a synthetic "__origin__" key whose value is +// a compact []interface{} sequence: +// [file, key_name, key_line, key_col, nf, f1_name, f1_delta, f1_col, ..., ns, s1_name, s1_count, (name, delta, col)×count, ...] +// where nf = number of scalar/sequence fields, ns = number of sequences with item locations, +// and deltas are line offsets from key_line. +``` + +Origin nodes are synthetic: their key node has `Line == 0` (since real YAML lines are 1-based), which allows callers to detect and strip them. The [oasdiff/yaml](https://github.com/oasdiff/yaml) package uses this to build an `OriginTree` before JSON conversion, keeping `__origin__` entirely out of the decoded struct. Introduction ------------ @@ -30,33 +47,19 @@ Specifically, as of v3 of the yaml package: - Does not support base-60 floats. These are gone from YAML 1.2, and were actually never supported by this package as it's clearly a poor choice. -and offers backwards -compatibility with YAML 1.1 in some cases. -1.2, including support for -anchors, tags, map merging, etc. Multi-document unmarshalling is not yet -implemented, and base-60 floats from YAML 1.1 are purposefully not -supported since they're a poor design and are gone in YAML 1.2. - Installation and usage ---------------------- -The import path for the package is *gopkg.in/yaml.v3*. +The import path for the package is *github.com/oasdiff/yaml3*. To install it, run: - go get gopkg.in/yaml.v3 + go get github.com/oasdiff/yaml3 API documentation ----------------- -If opened in a browser, the import path itself leads to the API documentation: - - - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3) - -API stability -------------- - -The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in). + - [https://pkg.go.dev/github.com/oasdiff/yaml3](https://pkg.go.dev/github.com/oasdiff/yaml3) License @@ -76,7 +79,7 @@ import ( "fmt" "log" - "oasdiff/yaml" + "github.com/oasdiff/yaml3" ) var data = ` diff --git a/vendor/github.com/oasdiff/yaml3/decode.go b/vendor/github.com/oasdiff/yaml3/decode.go index 0f2b9f9..293ddda 100644 --- a/vendor/github.com/oasdiff/yaml3/decode.go +++ b/vendor/github.com/oasdiff/yaml3/decode.go @@ -320,6 +320,7 @@ type decoder struct { knownFields bool origin bool + file string uniqueKeys bool decodeCount int aliasCount int @@ -525,6 +526,24 @@ func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { func (d *decoder) document(n *Node, out reflect.Value) (good bool) { if len(n.Content) == 1 { d.doc = n + if d.origin && d.aliasDepth == 0 { + root := n.Content[0] + if root.Kind == MappingNode && len(root.Content) >= 2 { + // Inject __origin__ into the root mapping of the document so that + // $ref-rooted YAML files (e.g. schemas/pet.yaml) expose origin + // metadata on their top-level schema, just like nested mappings do. + // Use the first key's position as the anchor for line-delta calculations. + firstKey := root.Content[0] + syntheticKey := &Node{ + Kind: ScalarNode, + Tag: "!!str", + Value: "", + Line: firstKey.Line, + Column: firstKey.Column, + } + addOriginInMap(syntheticKey, root, d.file) + } + } d.unmarshal(n.Content[0], out) return true } @@ -751,8 +770,8 @@ func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { j := 0 for i := 0; i < l; i++ { e := reflect.New(et).Elem() - if d.origin { - addOriginInSeq(n.Content[i]) + if d.origin && d.aliasDepth == 0 { + addOriginInSeq(n.Content[i], d.file) } if ok := d.unmarshal(n.Content[i], e); ok { out.Index(j).Set(e) @@ -832,6 +851,24 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { mergeNode = n.Content[i+1] continue } + // __origin__ metadata entries are injected when the anchor is first processed. + // Decoding them through the normal path would count toward aliasCount and + // could spuriously trigger the excessive-aliasing check on large specs. + // Decode them with aliasDepth temporarily zeroed so they don't count + // toward aliasCount, but the origin data is still present in the output. + if d.aliasDepth > 0 && isOrigin(n.Content[i]) { + savedAliasDepth := d.aliasDepth + d.aliasDepth = 0 + k := reflect.New(kt).Elem() + if d.unmarshal(n.Content[i], k) { + e := reflect.New(et).Elem() + if d.unmarshal(n.Content[i+1], e) { + out.SetMapIndex(k, e) + } + } + d.aliasDepth = savedAliasDepth + continue + } k := reflect.New(kt).Elem() if d.unmarshal(n.Content[i], k) { if mergedFields != nil { @@ -850,8 +887,8 @@ func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { } e := reflect.New(et).Elem() - if d.origin { - addOriginInMap(n.Content[i], n.Content[i+1]) + if d.origin && d.aliasDepth == 0 { + addOriginInMap(n.Content[i], n.Content[i+1], d.file) } if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { out.SetMapIndex(k, e) diff --git a/vendor/github.com/oasdiff/yaml3/origin.go b/vendor/github.com/oasdiff/yaml3/origin.go index b8ffa2c..cdcc60b 100644 --- a/vendor/github.com/oasdiff/yaml3/origin.go +++ b/vendor/github.com/oasdiff/yaml3/origin.go @@ -8,122 +8,117 @@ func isScalar(n *Node) bool { return n.Kind == ScalarNode } -func addOriginInSeq(n *Node) *Node { +func isSequence(n *Node) bool { + return n.Kind == SequenceNode +} - if n.Kind != MappingNode { +func addOriginInSeq(n *Node, file string) *Node { + if n.Kind != MappingNode || len(n.Content) == 0 { return n } - // in case of a sequence, we use the first element as the key - return addOrigin(n.Content[0], n) + return addOrigin(n.Content[0], n, file) } -func addOriginInMap(key, n *Node) *Node { - +func addOriginInMap(key, n *Node, file string) *Node { if n.Kind != MappingNode { return n } - - return addOrigin(key, n) + return addOrigin(key, n, file) } -func addOrigin(key, n *Node) *Node { +// addOrigin injects a compact __origin__ sequence into the mapping node n. +// +// Format: [file, key_name, key_line, key_col, nf, f1_name, f1_delta, f1_col, ..., ns, s1_name, s1_count, s1_l0_delta, s1_c0, ...] +// +// - file: source file path +// - key_name: the YAML key whose value is this mapping +// - key_line, key_col: location of that key +// - nf: number of scalar+sequence fields recorded +// - per field: name (string), line delta from key_line (int), column (int) +// - ns: number of sequence fields that have item locations +// - per sequence: name (string), item count (int), then count × (line delta, col) +func addOrigin(key, n *Node, file string) *Node { if isOrigin(key) { return n } - n.Content = append(n.Content, getNamedMap(originTag, append(getKeyLocation(key), getNamedMap("fields", getFieldLocations(n))...))...) + seq := buildOriginSeq(key, n, file) + n.Content = append(n.Content, + &Node{Kind: ScalarNode, Tag: "!!str", Value: originTag}, // Line==0 → isOrigin + &Node{Kind: SequenceNode, Tag: "!!seq", Content: seq}, + ) return n } -func getFieldLocations(n *Node) []*Node { +func buildOriginSeq(key, n *Node, file string) []*Node { + // Header: file, key_name, key_line, key_col + nodes := []*Node{ + strNode(file), + strNode(key.Value), + intNode(key.Line), + intNode(key.Column), + } + + // Collect field and sequence data. + var fieldNodes []*Node // nf × (name, delta, col) + var seqNodes []*Node // ns × (name, count, (delta, col)…) + nf, ns := 0, 0 l := len(n.Content) - size := 0 for i := 0; i < l; i += 2 { - if isScalar(n.Content[i+1]) { - size += 2 + k := n.Content[i] + v := n.Content[i+1] + if isOrigin(k) { + continue } - } - - nodes := make([]*Node, 0, size) - for i := 0; i < l; i += 2 { - if isScalar(n.Content[i+1]) { - nodes = append(nodes, getNodeLocation(n.Content[i])...) + if isScalar(v) || isSequence(v) { + // Record the location of this field's key. + nf++ + fieldNodes = append(fieldNodes, + strNode(k.Value), + intNode(k.Line-key.Line), + intNode(k.Column), + ) + } + if isSequence(v) { + // Record locations of scalar items within the sequence. + // Format per item: value_str, line_delta, col + var itemNodes []*Node + for _, item := range v.Content { + if item.Kind == ScalarNode { + itemNodes = append(itemNodes, + strNode(item.Value), + intNode(item.Line-key.Line), + intNode(item.Column), + ) + } + } + if len(itemNodes) > 0 { + ns++ + seqNodes = append(seqNodes, strNode(k.Value), intNode(len(itemNodes)/3)) + seqNodes = append(seqNodes, itemNodes...) + } } } + + nodes = append(nodes, intNode(nf)) + nodes = append(nodes, fieldNodes...) + nodes = append(nodes, intNode(ns)) + nodes = append(nodes, seqNodes...) return nodes } -// isOrigin returns true if the key is an "origin" element -// the current implementation is not optimal, as it relies on the key's line number -// a better design would be to use a dedicated field in the Node struct +// isOrigin returns true if the key is a synthetic origin node. +// Synthetic nodes have Line==0 (real YAML lines are 1-based). func isOrigin(key *Node) bool { return key.Line == 0 } -func getNodeLocation(n *Node) []*Node { - return getNamedMap(n.Value, getLocationObject(n)) +func strNode(v string) *Node { + return &Node{Kind: ScalarNode, Tag: "!!str", Value: v} } -func getKeyLocation(n *Node) []*Node { - return getNamedMap("key", getLocationObject(n)) -} - -func getNamedMap(title string, content []*Node) []*Node { - if len(content) == 0 { - return nil - } - - return []*Node{ - { - Kind: ScalarNode, - Tag: "!!str", - Value: title, - }, - getMap(content), - } -} - -func getMap(content []*Node) *Node { - return &Node{ - Kind: MappingNode, - Tag: "!!map", - Content: content, - } -} - -func getLocationObject(key *Node) []*Node { - return []*Node{ - { - Kind: ScalarNode, - Tag: "!!str", - Value: "line", - }, - { - Kind: ScalarNode, - Tag: "!!int", - Value: fmt.Sprintf("%d", key.Line), - }, - { - Kind: ScalarNode, - Tag: "!!str", - Value: "column", - }, - { - Kind: ScalarNode, - Tag: "!!int", - Value: fmt.Sprintf("%d", key.Column), - }, - { - Kind: ScalarNode, - Tag: "!!str", - Value: "name", - }, - { - Kind: ScalarNode, - Tag: "!!string", - Value: key.Value, - }, - } +func intNode(v int) *Node { + return &Node{Kind: ScalarNode, Tag: "!!int", Value: fmt.Sprintf("%d", v)} } diff --git a/vendor/github.com/oasdiff/yaml3/yaml.go b/vendor/github.com/oasdiff/yaml3/yaml.go index a49a19b..9cec8a8 100644 --- a/vendor/github.com/oasdiff/yaml3/yaml.go +++ b/vendor/github.com/oasdiff/yaml3/yaml.go @@ -92,6 +92,7 @@ type Decoder struct { parser *parser knownFields bool origin bool + file string } // NewDecoder returns a new decoder that reads from r. @@ -112,8 +113,9 @@ func (dec *Decoder) KnownFields(enable bool) { // Origin enables the recording of the line and column of the // decoded values in the YAML content. -func (dec *Decoder) Origin(enable bool) { +func (dec *Decoder) Origin(enable bool, file string) { dec.origin = enable + dec.file = file } // Decode reads the next YAML-encoded value from its input @@ -125,6 +127,7 @@ func (dec *Decoder) Decode(v interface{}) (err error) { d := newDecoder() d.knownFields = dec.knownFields d.origin = dec.origin + d.file = dec.file defer handleErr(&err) node := dec.parser.parse() if node == nil { diff --git a/vendor/modules.txt b/vendor/modules.txt index 47bf6b7..2c150ac 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,7 +4,7 @@ github.com/clipperhouse/uax29/v2/graphemes # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew/spew -# github.com/getkin/kin-openapi v0.133.0 +# github.com/getkin/kin-openapi v0.135.0 ## explicit; go 1.22.5 github.com/getkin/kin-openapi/openapi3 # github.com/go-chi/chi/v5 v5.2.5 @@ -81,15 +81,13 @@ github.com/mattn/go-runewidth # github.com/mitchellh/go-homedir v1.1.0 ## explicit github.com/mitchellh/go-homedir -# github.com/mitchellh/mapstructure v1.5.0 -## explicit; go 1.14 # github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 ## explicit github.com/mohae/deepcopy -# github.com/oasdiff/yaml v0.0.0-20250309154309-f31be36b4037 +# github.com/oasdiff/yaml v0.0.9 ## explicit; go 1.22.5 github.com/oasdiff/yaml -# github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 +# github.com/oasdiff/yaml3 v0.0.9 ## explicit; go 1.22.5 github.com/oasdiff/yaml3 # github.com/perimeterx/marshmallow v1.1.5 @@ -98,8 +96,6 @@ github.com/perimeterx/marshmallow # github.com/pmezard/go-difflib v1.0.0 ## explicit github.com/pmezard/go-difflib/difflib -# github.com/rivo/uniseg v0.4.7 -## explicit; go 1.18 # github.com/rs/zerolog v1.34.0 ## explicit; go 1.15 github.com/rs/zerolog