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