It’s that time of year again, so I’m playing with compojure-api 🙂
And I have this route:
(GET "/" {system :system :as request}
:coercion :spec
:summary "Returns all the things"
:return (spec-tools/merge ::specs/identifiable
::specs/named
(spec/keys :opt-un [::specs/description]))
[])
Which shows up in the swagger ui, which is great, but it doesn’t show anything useful in for the return value, it only shows {}
If I change to
(GET "/" {system :system :as request}
:coercion :spec
:summary "Returns all the things"
:return (spec/merge ::specs/identifiable
::specs/named
(spec/keys :opt-un [::specs/description]))
[])
I get
{
"_id": "string",
"name": "string",
"description": "string"
}
as expected.
You can run the transformation from repl, something like:
(require '[spec-tools.swagger.core :as swagger])
(swagger/transform (spec-tools/merge ::specs/identifiable
::specs/named
(spec/keys :opt-un [::specs/description])))
… to see what pops up.
ardoq.api.crud-api-v2> (swagger/transform (spec/merge ::specs/identifiable
::specs/named
(spec/keys :opt-un [::specs/description])))
;; => {:type "object",
:properties
{"_id"
{:type "string",
:x-allOf [{:type "string"} {}],
:title "ardoq.specs/_id"},
"name" {:type "string"},
"description" {:type "string", :x-nullable true}},
:required ["_id" "name"]}
ardoq.api.crud-api-v2> (swagger/transform (spec-tools/merge ::specs/identifiable
::specs/named
(spec/keys :opt-un [::specs/description])))
;; => {}
ardoq.api.crud-api-v2>
oh, and no tests for st/merge
either: https://github.com/metosin/spec-tools/blob/master/test/cljc/spec_tools/swagger/core_test.cljc
and somewhat involved, IIRC 🙂
now that you know it’s not working properly, would you have time to make a PR? 😉
I have time to make an issue, but I don’t know if I’m capable of creating a PR.
Issue is good, I should have time to check if that’s a small fix or needs more time. most likely just missing a multimethod dispatch for that.
but now just now (the time)
user> (defmethod swagger/accept-spec 'spec-tools.core/merge [_ _ children _]
;; Use x-anyOf and x-allOf instead of normal versions
{:type "object"
:properties (->> (concat children
(mapcat :x-anyOf children)
(mapcat :x-allOf children))
(map :properties)
(reduce merge {}))
;; Don't include top schema from s/or.
:required (->> (concat (remove :x-anyOf children)
(mapcat :x-allOf children))
(map :required)
(reduce into (sorted-set))
(into []))})
;; => #multifn[accept-spec 0x3f8c13a8]
user> (swagger/transform (spec-tools/merge ::has-string ::has-int))
;; => {:type "object", :properties {}, :required []}
user>
Closer, but still no cigar 🙂
you have mad skills at extending libraries 🙂
children
is nil for spec-tools.core/merge
you need to check also from the visitor
ns that there is a mm dispatch to walk the childs.
it goes: 1) visitor walks the specs (need an mm for all form symbols) 2) json-schema is used as a base transfromation 3) swagger overrides the stuff that it can’t handle
You Rock!!
user> (swagger/transform (spec-tools/merge ::has-string ::has-int))
;; => {:type "object",
:properties
{"string" {:type "string"},
"int" {:type "integer", :format "int64"}},
:required ["int" "string"]}
user>
I might just have time to make a pr after all 🙂
awesome! 🙂
seems to be the same case for spec/coll-of
I’ve got another sort of weird case:
(POST "/" {{document :json-params} :params
system :system :as request}
:coercion :no-coercion
:summary "Create one thing"
:body [document spec]
:return (spec/merge spec ::specs/metadata)
(create* (service-kw system) (request-util/->context request) spec document)))))
only returns the first of the merged specs. It works as expected if :return
only contains spec
(which is also a result of a merged spec)
I’ll be happy to file an issue for this if it’s supposed to be supported like this.
Here’s the issue for coll-of
https://github.com/metosin/spec-tools/issues/175