diff --git a/go.mod b/go.mod index 6cc4dd2..8579348 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.134.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.0-20260313112342-a3ea61cb4d4c // indirect + github.com/oasdiff/yaml3 v0.0.0-20260224194419-61cd415a242b // 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..b3ef5f3 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.134.0 h1:/L5+1+kfe6dXh8Ot/wqiTgUkjOIEJiC0bbYVziHB8rU= +github.com/getkin/kin-openapi v0.134.0/go.mod h1:wK6ZLG/VgoETO9pcLJ/VmAtIcl/DNlMayNTb716EUxE= 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.0-20260313112342-a3ea61cb4d4c h1:7ACFcSaQsrWtrH4WHHfUqE1C+f8r2uv8KGaW0jTNjus= +github.com/oasdiff/yaml v0.0.0-20260313112342-a3ea61cb4d4c/go.mod h1:JKox4Gszkxt57kj27u7rvi7IFoIULvCZHUsBTUmQM/s= +github.com/oasdiff/yaml3 v0.0.0-20260224194419-61cd415a242b h1:vivRhVUAa9t1q0Db4ZmezBP8pWQWnXHFokZj0AOea2g= +github.com/oasdiff/yaml3 v0.0.0-20260224194419-61cd415a242b/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/discriminator.go b/vendor/github.com/getkin/kin-openapi/openapi3/discriminator.go index 6934c17..faf53dc 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. diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/example.go b/vendor/github.com/getkin/kin-openapi/openapi3/example.go index 44d5777..5dde017 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/example.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/example.go @@ -69,6 +69,7 @@ func (example *Example) UnmarshalJSON(data []byte) error { x.Extensions = nil } *example = Example(x) + example.Value = stripOriginFromAny(example.Value) return nil } 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/link.go b/vendor/github.com/getkin/kin-openapi/openapi3/link.go index c76cf44..483750c 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/link.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/link.go @@ -79,6 +79,7 @@ func (link *Link) UnmarshalJSON(data []byte) error { x.Extensions = nil } *link = Link(x) + link.RequestBody = stripOriginFromAny(link.RequestBody) return nil } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/loader.go b/vendor/github.com/getkin/kin-openapi/openapi3/loader.go index 67674fc..1e9e648 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/loader.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/loader.go @@ -108,7 +108,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, IncludeOrigin, resolvedPath); err != nil { return nil, err } @@ -144,7 +144,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, IncludeOrigin, nil); err != nil { return nil, err } if err := loader.ResolveRefsIn(doc, nil); err != nil { @@ -173,7 +173,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, IncludeOrigin, location); err != nil { return nil, err } @@ -427,7 +427,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, IncludeOrigin, path); err2 != nil { return nil, nil, err } if cursor, err2 = drill(cursor); err2 != nil || cursor == nil { @@ -970,6 +970,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/marsh.go b/vendor/github.com/getkin/kin-openapi/openapi3/marsh.go index 2f00828..657862f 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,7 +26,11 @@ 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.Path + } + if yamlErr = yaml.UnmarshalWithOrigin(data, v, yaml.OriginOpt{Enabled: includeOrigin, File: file}); yamlErr == nil { return nil } 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..c3bb1be 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/media_type.go @@ -111,6 +111,7 @@ func (mediaType *MediaType) UnmarshalJSON(data []byte) error { x.Extensions = nil } *mediaType = MediaType(x) + mediaType.Example = stripOriginFromAny(mediaType.Example) return 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/origin.go b/vendor/github.com/getkin/kin-openapi/openapi3/origin.go index d2a51d9..d961214 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/origin.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/origin.go @@ -4,14 +4,35 @@ const originKey = "__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"` +} + +// stripOriginFromAny recursively removes the __origin__ key from any +// map[string]any value. This is needed for interface{}/any-typed fields +// (e.g. Schema.Enum, Schema.Default, Parameter.Example) that have no +// dedicated UnmarshalJSON to consume the origin metadata injected by +// the YAML origin-tracking loader. +func stripOriginFromAny(v any) any { + m, ok := v.(map[string]any) + if !ok { + return v + } + delete(m, originKey) + for k, val := range m { + m[k] = stripOriginFromAny(val) + } + return m } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go b/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go index 23582f7..ceea1f2 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/parameter.go @@ -236,6 +236,7 @@ func (parameter *Parameter) UnmarshalJSON(data []byte) error { } *parameter = Parameter(x) + parameter.Example = stripOriginFromAny(parameter.Example) return nil } 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..185275e 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/refs.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/refs.go @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() } @@ -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() } diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl b/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl index 028deba..244a7d6 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl +++ b/vendor/github.com/getkin/kin-openapi/openapi3/refs.tmpl @@ -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() } 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/schema.go b/vendor/github.com/getkin/kin-openapi/openapi3/schema.go index d76bef4..9ccba38 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/schema.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/schema.go @@ -469,6 +469,12 @@ func (schema *Schema) UnmarshalJSON(data []byte) error { *schema = Schema(x) + for i, v := range schema.Enum { + schema.Enum[i] = stripOriginFromAny(v) + } + schema.Default = stripOriginFromAny(schema.Default) + schema.Example = stripOriginFromAny(schema.Example) + if schema.Format == "date" { // This is a fix for: https://github.com/getkin/kin-openapi/issues/697 if eg, ok := schema.Example.(string); ok { @@ -1299,7 +1305,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 +1351,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 +1533,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 +1552,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 +1783,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{} @@ -2144,6 +2165,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 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_scheme.go b/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go index 676002a..b874cca 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/security_scheme.go @@ -322,10 +322,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. diff --git a/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go b/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go index d1b91ac..10e7e6d 100644 --- a/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go +++ b/vendor/github.com/getkin/kin-openapi/openapi3/stringmap.go @@ -3,11 +3,11 @@ 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 } diff --git a/vendor/github.com/oasdiff/yaml/yaml.go b/vendor/github.com/oasdiff/yaml/yaml.go index c49678e..6a2c375 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 @@ -44,14 +44,21 @@ 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...) + return UnmarshalWithOrigin(y, o, OriginOpt{}, opts...) } -// 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 { +// OriginOpt controls origin-tracking behavior in UnmarshalWithOrigin. +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 +} + +// UnmarshalWithOrigin is like Unmarshal but supports origin tracking via OriginOpt. +func UnmarshalWithOrigin(y []byte, o interface{}, origin OriginOpt, opts ...JSONOpt) error { dec := yaml.NewDecoder(bytes.NewReader(y)) - dec.Origin(withOrigin) + dec.Origin(origin.Enabled, origin.File) return unmarshal(dec, o, opts) } @@ -142,6 +149,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/decode.go b/vendor/github.com/oasdiff/yaml3/decode.go index 0f2b9f9..c7a64d3 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 @@ -752,7 +753,7 @@ func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { for i := 0; i < l; i++ { e := reflect.New(et).Elem() if d.origin { - addOriginInSeq(n.Content[i]) + addOriginInSeq(n.Content[i], d.file) } if ok := d.unmarshal(n.Content[i], e); ok { out.Index(j).Set(e) @@ -851,7 +852,7 @@ 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]) + 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..c33ddc6 100644 --- a/vendor/github.com/oasdiff/yaml3/origin.go +++ b/vendor/github.com/oasdiff/yaml3/origin.go @@ -8,53 +8,95 @@ func isScalar(n *Node) bool { return n.Kind == ScalarNode } -func addOriginInSeq(n *Node) *Node { +func isSequence(n *Node) bool { + return n.Kind == SequenceNode +} + +func addOriginInSeq(n *Node, file string) *Node { if n.Kind != MappingNode { 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 { +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))...))...) + content := getKeyLocation(key, file) + content = append(content, getNamedMap("fields", getFieldLocations(n, file))...) + content = append(content, getNamedMap("sequences", getSequenceLocations(n, file))...) + n.Content = append(n.Content, getNamedMap(originTag, content)...) return n } -func getFieldLocations(n *Node) []*Node { +func getFieldLocations(n *Node, file string) []*Node { l := len(n.Content) size := 0 for i := 0; i < l; i += 2 { - if isScalar(n.Content[i+1]) { + if isScalar(n.Content[i+1]) || isSequence(n.Content[i+1]) { size += 2 } } 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(n.Content[i+1]) || isSequence(n.Content[i+1]) { + nodes = append(nodes, getNodeLocation(n.Content[i], file)...) + } + } + return nodes +} + +func getSequenceLocations(n *Node, file string) []*Node { + l := len(n.Content) + var nodes []*Node + for i := 0; i < l; i += 2 { + if isSequence(n.Content[i+1]) { + nodes = append(nodes, getNamedSeq(n.Content[i].Value, n.Content[i+1], file)...) } } return nodes } +func getNamedSeq(title string, seq *Node, file string) []*Node { + var items []*Node + for _, item := range seq.Content { + if item.Kind == ScalarNode { + items = append(items, getMap(getLocationObject(item, file))) + } + } + if len(items) == 0 { + return nil + } + return []*Node{ + { + Kind: ScalarNode, + Tag: "!!str", + Value: title, + }, + { + Kind: SequenceNode, + Tag: "!!seq", + Content: items, + }, + } +} + // 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 @@ -62,12 +104,12 @@ func isOrigin(key *Node) bool { return key.Line == 0 } -func getNodeLocation(n *Node) []*Node { - return getNamedMap(n.Value, getLocationObject(n)) +func getNodeLocation(n *Node, file string) []*Node { + return getNamedMap(n.Value, getLocationObject(n, file)) } -func getKeyLocation(n *Node) []*Node { - return getNamedMap("key", getLocationObject(n)) +func getKeyLocation(n *Node, file string) []*Node { + return getNamedMap("key", getLocationObject(n, file)) } func getNamedMap(title string, content []*Node) []*Node { @@ -93,8 +135,18 @@ func getMap(content []*Node) *Node { } } -func getLocationObject(key *Node) []*Node { +func getLocationObject(key *Node, file string) []*Node { return []*Node{ + { + Kind: ScalarNode, + Tag: "!!str", + Value: "file", + }, + { + Kind: ScalarNode, + Tag: "!!str", + Value: file, + }, { Kind: ScalarNode, Tag: "!!str", 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..61bcc0c 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.134.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.0-20260313112342-a3ea61cb4d4c ## explicit; go 1.22.5 github.com/oasdiff/yaml -# github.com/oasdiff/yaml3 v0.0.0-20250309153720-d2182401db90 +# github.com/oasdiff/yaml3 v0.0.0-20260224194419-61cd415a242b ## 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