Finalize malli coercion

This commit is contained in:
Tommi Reiman 2019-12-28 02:20:40 +02:00
parent dc718e07e7
commit 44f6c51610
3 changed files with 74 additions and 75 deletions

View file

@ -1,6 +1,8 @@
(ns reitit.coercion.malli
(:require [reitit.coercion :as coercion]
[malli.transform :as mt]
[malli.edn :as edn]
[malli.error :as me]
[malli.swagger :as swagger]
[malli.core :as m]
[clojure.set :as set]))
@ -49,12 +51,9 @@
(if (validator transformed)
transformed
(let [explainer (:explainer coercer)
errors (explainer transformed)]
error (explainer transformed)]
(coercion/map->CoercionError
{:schema schema
:value value
:transformed transformed
:errors errors}))))
(assoc error :transformed transformed)))))
value))
;; validate -> transform
(fn [value format]
@ -65,9 +64,7 @@
(if (validator value)
(transform value)
(coercion/map->CoercionError
{:schema schema
:value value
:errors (explainer value)})))
(explainer value))))
value)))))))
;;
@ -108,46 +105,58 @@
:string {:default string-transformer}
:response {:default default-transformer
:formats {"application/json" json-transformer}}}
;; set of keys to include in error messages
:error-keys #{:type :coercion :in #_:schema #_:value :errors :humanized #_:transformed}
;; malli options
:options nil})
(defn create [opts]
(let [{:keys [transformers coerce-response? options] :as opts} (merge default-options opts)]
^{:type ::coercion/coercion}
(reify coercion/Coercion
(-get-name [_] :malli)
(-get-options [_] opts)
(-get-apidocs [_ specification {:keys [parameters responses]}]
(case specification
:swagger (merge
(if parameters
{:parameters
(->> (for [[in schema] parameters
parameter (extract-parameter in schema)]
parameter)
(into []))})
(if responses
{:responses
(into
(empty responses)
(for [[status response] responses]
[status (as-> response $
(set/rename-keys $ {:body :schema})
(update $ :description (fnil identity ""))
(if (:schema $)
(update $ :schema swagger/transform {:type :schema})
$))]))}))
(throw
(ex-info
(str "Can't produce Schema apidocs for " specification)
{:type specification, :coercion :schema}))))
(-compile-model [_ model _] (m/schema model))
(-open-model [_ schema] schema)
(-encode-error [_ error] error)
(-request-coercer [_ type schema]
(-coercer schema type transformers :decode options))
(-response-coercer [_ schema]
(if (coerce-response? schema)
(-coercer schema :response transformers :encode options))))))
(defn create
([]
(create nil))
([opts]
(let [{:keys [transformers coerce-response? options error-keys] :as opts} (merge default-options opts)
show? (fn [key] (contains? error-keys key))]
^{:type ::coercion/coercion}
(reify coercion/Coercion
(-get-name [_] :malli)
(-get-options [_] opts)
(-get-apidocs [_ specification {:keys [parameters responses]}]
(case specification
:swagger (merge
(if parameters
{:parameters
(->> (for [[in schema] parameters
parameter (extract-parameter in schema)]
parameter)
(into []))})
(if responses
{:responses
(into
(empty responses)
(for [[status response] responses]
[status (as-> response $
(set/rename-keys $ {:body :schema})
(update $ :description (fnil identity ""))
(if (:schema $)
(update $ :schema swagger/transform {:type :schema})
$))]))}))
(throw
(ex-info
(str "Can't produce Schema apidocs for " specification)
{:type specification, :coercion :schema}))))
(-compile-model [_ model _] (m/schema model))
(-open-model [_ schema] schema)
(-encode-error [_ error]
(cond-> error
(show? :humanized) (assoc :humanized (me/humanize error {:wrap :message}))
(show? :schema) (update :schema edn/write-string opts)
(show? :errors) (-> (me/with-error-messages opts)
(update :errors (partial map #(update % :schema edn/write-string opts))))
true (select-keys error-keys)))
(-request-coercer [_ type schema]
(-coercer schema type transformers :decode options))
(-response-coercer [_ schema]
(if (coerce-response? schema)
(-coercer schema :response transformers :encode options)))))))
(def coercion (create default-options))

View file

@ -0,0 +1,19 @@
(ns reitit.ring.malli
#?(:clj (:import (java.io File))))
#?(:clj
(def temp-file-part
"Schema for file param created by ring.middleware.multipart-params.temp-file store."
[:map {:json-schema {:type "file"}}
[:filename string?]
[:content-type string?]
[:size int?]
[:tempfile [:fn (partial instance? File)]]]))
#?(:clj
(def bytes-part
"Schema for file param created by ring.middleware.multipart-params.byte-array store."
[:map {:json-schema {:type "file"}}
[:filename string?]
[:content-type string?]
[:bytes bytes?]]))

View file

@ -1,29 +0,0 @@
(ns reitit.ring.malli)
(comment
(defrecord Upload [m]
s/Schema
(spec [_]
(s/spec m))
(explain [_]
(list 'file m))
swagger/SwaggerSchema
(-transform [_ _]
{:type "file"}))
#?(:clj
(def TempFilePart
"Schema for file param created by ring.middleware.multipart-params.temp-file store."
(->Upload {:filename s/Str
:content-type s/Str
:size s/Int
:tempfile File})))
#?(:clj
(def BytesPart
"Schema for file param created by ring.middleware.multipart-params.byte-array store."
(->Upload {:filename s/Str
:content-type s/Str
:bytes s/Any}))))