malli
malli copied to clipboard
Unexpected reference while generating swagger specs with custom types
I'm trying to use custom types and customize its swagger spec output.
On this example, I simplified a lot. In my actual code, :my/int
is created via malli.core/-simple-schema
.
But we can see the unexpected behavior in this code:
(require '[malli.core :as m]
'[malli.swagger :as ms])
(ms/transform [:map
[:ok :int]
[:notok :my/int]]
{:registry (assoc (m/default-schemas)
:my/int (m/-simple-schema {:type :my/int
:pred int?
:property-pred (m/-min-max-pred nil)}))})
=> {:type "object",
:properties {:ok {:type "integer"
:format "int64"}
:notok
;; expected
#_{:type "integer", :format "int64"}
;; actual
{:$ref "#/definitions/:my/int"}}
:required [:ok :notok]
;; not expected
:definitions {:my/int {:type "integer", :format "int64"}}}
I don't want to generate a ref to this type. I just want to put it "in-place"
It seems Malli puts "in-place" only non-qualified keywords, no idea why
(malli.swagger/transform
(mu/closed-schema
[:map {:registry {:eita/schema :int}}
[:a :eita/schema]]))
;; =>
{:type "object",
:properties {:a {:type "integer", :format "int64"}},
:required [:a]}
(malli.swagger/transform
[:map {:registry {:eita/schema :int}}
[:a :eita/schema]])
;; =>
{:type "object",
:properties {:a {:$ref "#/definitions/:eita/schema"}},
:required [:a],
:definitions #:eita{:schema {:type "integer", :format "int64"}}}
I see. Ideas welcome on how to change this in an elegant way.
More wired behaviors. Still trying to understand the root cause.
(def opts
{:registry (assoc (m/default-schemas)
:my/int (m/-simple-schema
;; exactly the same as :int
{:type :my/int
:pred int?
:property-pred (m/-min-max-pred nil)}))})
(m/ast :int opts) #_#_=> {:type :int}
(m/ast [:int] opts) #_#_=> {:type :int}
;; wired: m/ast behaves differently between equivalent notations
;; root cause: https://github.com/metosin/malli/blob/0.8.9/src/malli/core.cljc#L1994
;; seems that -reference? function is the problem
(m/ast :my/int opts) #_#_=> {:type :malli.core/schema, :value :my/int}
(m/ast [:my/int] opts) #_#_=> {:type :my/int}
;; transform with kw: not what I expect
(ms/transform :my/int opts) #_#_=> {:$ref "#/definitions/:my/int", :definitions {:my/int {}}}
;; transform with []: wrong
(ms/transform [:my/int] opts) #_#_=> {}
Digged into this. I think the bug is actually how the non-qualified types are used, e.g.
(m/form [:schema {:registry {:my-int :int}} :my-int])
; => [:schema {:registry {:my-int :int}} :int]
.. the last child is of type :malli.core/schema
but due to malli internals to form will show in inlined value. This is not good as we are losing information. This should be fixed.
Another - how do define qualified keys (or string) that are not reference values, just values. I think a good way would be to change internals so that any value in the registry that is a IntoSchema
instance, should not be handled as a reference, just a type instead. This would allow tools like the swagger/openapi transformers not to create references out of those.
https://github.com/metosin/malli/issues/749