feat: openapi #/components/schemas

collect definitions when traversing the models, and put them in the
right place for openapi

depends on :malli.json-schema/definitions-path support
This commit is contained in:
Joel Kaasinen 2024-04-19 10:57:51 +03:00
parent c2372473d0
commit 288b701d4e
2 changed files with 22 additions and 14 deletions

View file

@ -77,7 +77,7 @@
(-> path (trie/normalize opts) (str/replace #"\{\*" "{")))
(defn -get-apidocs-openapi
[coercion {:keys [request muuntaja parameters responses openapi/request-content-types openapi/response-content-types]}]
[coercion {:keys [request muuntaja parameters responses openapi/request-content-types openapi/response-content-types]} definitions]
(let [{:keys [body multipart]} parameters
parameters (dissoc parameters :request :body :multipart)
->content (fn [data schema]
@ -85,7 +85,13 @@
{:schema schema}
(select-keys data [:description :examples])
(:openapi data)))
->schema-object #(coercion/-get-model-apidocs coercion :openapi %1 %2)
->schema-object (fn [model opts]
(let [result (coercion/-get-model-apidocs
coercion :openapi model
(assoc opts :malli.json-schema/definitions-path "#/components/schemas/"))]
(when-let [d (:definitions result)]
(vswap! definitions merge d))
(dissoc result :definitions)))
request-content-types (or request-content-types
(when muuntaja (m/decodes muuntaja))
["application/json"])
@ -189,6 +195,7 @@
:x-id ids}))
accept-route (fn [route]
(-> route second :openapi :id (or ::default) (trie/into-set) (set/intersection ids) seq))
definitions (volatile! {})
transform-endpoint (fn [[method {{:keys [coercion no-doc openapi] :as data} :data
middleware :middleware
interceptors :interceptors}]]
@ -198,7 +205,7 @@
(apply meta-merge (keep (comp :openapi :data) middleware))
(apply meta-merge (keep (comp :openapi :data) interceptors))
(if coercion
(-get-apidocs-openapi coercion data))
(-get-apidocs-openapi coercion data definitions))
(select-keys data [:tags :summary :description])
(strip-top-level-keys openapi))]))
transform-path (fn [[p _ c]]
@ -207,7 +214,8 @@
map-in-order #(->> % (apply concat) (apply array-map))
paths (->> router (r/compiled-routes) (filter accept-route) (map transform-path) map-in-order)]
{:status 200
:body (meta-merge openapi {:paths paths})}))
:body (cond-> (meta-merge openapi {:paths paths})
(seq @definitions) (assoc-in [:components :schemas] @definitions))}))
([req res raise]
(try
(res (create-openapi req))

View file

@ -844,16 +844,16 @@
:requestBody
{:content
{"application/json"
{:schema {:$ref "#/definitions/friend"
:definitions {"friend" {:properties {:age {:type "integer"}
:pet {:$ref "#/definitions/pet"}}
:required [:age :pet]
:type "object"}
"pet" {:properties {:friends {:items {:$ref "#/definitions/friend"}
:type "array"}
:name {:type "string"}}
:required [:name :friends]
:type "object"}}}}}}}}}}
{:schema {:$ref "#/components/schemas/friend"}}}}}}}
:components {:schemas {"friend" {:properties {:age {:type "integer"}
:pet {:$ref "#/components/schemas/pet"}}
:required [:age :pet]
:type "object"}
"pet" {:properties {:friends {:items {:$ref "#/components/schemas/friend"}
:type "array"}
:name {:type "string"}}
:required [:name :friends]
:type "object"}}}}
spec))
(testing "spec is valid"
(is (nil? (validate spec))))))