Move route-data merge impl to coercion protocol

This commit is contained in:
Juho Teperi 2021-12-26 00:31:52 +02:00
parent 5529e5acf0
commit 28707fff07
7 changed files with 45 additions and 31 deletions

View file

@ -17,7 +17,8 @@
(-open-model [this model] "Returns a new model which allows extra keys in maps") (-open-model [this model] "Returns a new model which allows extra keys in maps")
(-encode-error [this error] "Converts error in to a serializable format") (-encode-error [this error] "Converts error in to a serializable format")
(-request-coercer [this type model] "Returns a `value format => value` request coercion function") (-request-coercer [this type model] "Returns a `value format => value` request coercion function")
(-response-coercer [this model] "Returns a `value format => value` response coercion function")) (-response-coercer [this model] "Returns a `value format => value` response coercion function")
(-route-data-merge [this acc k v]))
#?(:clj #?(:clj
(defmethod print-method ::coercion [coercion ^Writer w] (defmethod print-method ::coercion [coercion ^Writer w]

View file

@ -360,8 +360,7 @@
| `:validate` | Function of `routes opts => ()` to validate route (data) via side-effects | `:validate` | Function of `routes opts => ()` to validate route (data) via side-effects
| `:conflicts` | Function of `{route #{route}} => ()` to handle conflicting routes | `:conflicts` | Function of `{route #{route}} => ()` to handle conflicting routes
| `:exception` | Function of `Exception => Exception ` to handle creation time exceptions (default `reitit.exception/exception`) | `:exception` | Function of `Exception => Exception ` to handle creation time exceptions (default `reitit.exception/exception`)
| `:router` | Function of `routes opts => router` to override the actual router implementation | `:router` | Function of `routes opts => router` to override the actual router implementation"
| `:merge` | Function of `route-data key value` to add new kv pair to route-data map. Default uses merge-merge."
([raw-routes] ([raw-routes]
(router raw-routes {})) (router raw-routes {}))
([raw-routes opts] ([raw-routes opts]

View file

@ -63,18 +63,30 @@
(defn default-route-data-merge [acc k v] (defn default-route-data-merge [acc k v]
(mm/meta-merge acc {k v})) (mm/meta-merge acc {k v}))
(defn merge-data [route-data-merge p x] (defn merge-data [p x]
(let [;; Find last the effective :coercion value
;; for the route, and then use the cocercion
;; instance for route data merge implementation.
coercion (->> x
reverse
(some (fn [[k v]]
(when (= :coercion k)
v))))
route-data-merge (if coercion
#((resolve 'reitit.coercion/-route-data-merge) coercion %1 %2 %3)
default-route-data-merge)]
(reduce (reduce
(fn [acc [k v]] (fn [acc [k v]]
(try (try
(route-data-merge acc k v) (route-data-merge acc k v)
(catch #?(:clj Exception, :cljs js/Error) e (catch #?(:clj Exception, :cljs js/Error) e
(ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e})))) (ex/fail! ::merge-data {:path p, :left acc, :right {k v}, :exception e}))))
{} x)) {}
x)))
(defn resolve-routes [raw-routes {:keys [coerce _merge] :as opts}] (defn resolve-routes [raw-routes {:keys [coerce] :as opts}]
(cond->> (->> (walk raw-routes opts) (cond->> (->> (walk raw-routes opts)
(map-data (partial merge-data (or (:merge opts) default-route-data-merge)))) (map-data merge-data))
coerce (into [] (keep #(coerce % opts))))) coerce (into [] (keep #(coerce % opts)))))
(defn path-conflicting-routes [routes opts] (defn path-conflicting-routes [routes opts]

View file

@ -180,11 +180,10 @@
(-request-coercer [_ type schema] (-request-coercer [_ type schema]
(-coercer (compile schema options) type transformers :decode opts)) (-coercer (compile schema options) type transformers :decode opts))
(-response-coercer [_ schema] (-response-coercer [_ schema]
(-coercer (compile schema options) :response transformers :encode opts)))))) (-coercer (compile schema options) :response transformers :encode opts))
(-route-data-merge [_ acc k v]
(def coercion (create default-options))
(defn route-data-merge [acc k v]
(case k (case k
:parameters (assoc acc :parameters (merge-with mu/merge (:parameters acc) v)) :parameters (assoc acc :parameters (merge-with mu/merge (:parameters acc) v))
(mm/meta-merge acc {k v}))) (mm/meta-merge acc {k v})))))))
(def coercion (create default-options))

View file

@ -7,7 +7,8 @@
[schema-tools.coerce :as stc] [schema-tools.coerce :as stc]
[schema-tools.swagger.core :as swagger] [schema-tools.swagger.core :as swagger]
[reitit.coercion :as coercion] [reitit.coercion :as coercion]
[clojure.set :as set])) [clojure.set :as set]
[reitit.impl :as impl]))
(def string-coercion-matcher (def string-coercion-matcher
stc/string-coercion-matcher) stc/string-coercion-matcher)
@ -94,6 +95,8 @@
value)))) value))))
(-response-coercer [this schema] (-response-coercer [this schema]
(if (coerce-response? schema) (if (coerce-response? schema)
(coercion/-request-coercer this :response schema))))) (coercion/-request-coercer this :response schema)))
(-route-data-merge [this acc k v]
(impl/default-route-data-merge acc k v))))
(def coercion (create default-options)) (def coercion (create default-options))

View file

@ -4,6 +4,7 @@
[spec-tools.data-spec :as ds #?@(:cljs [:refer [Maybe]])] [spec-tools.data-spec :as ds #?@(:cljs [:refer [Maybe]])]
[spec-tools.swagger.core :as swagger] [spec-tools.swagger.core :as swagger]
[reitit.coercion :as coercion] [reitit.coercion :as coercion]
[reitit.impl :as impl]
[clojure.set :as set]) [clojure.set :as set])
#?(:clj #?(:clj
(:import (spec_tools.core Spec) (:import (spec_tools.core Spec)
@ -135,6 +136,8 @@
value)))) value))))
(-response-coercer [this spec] (-response-coercer [this spec]
(if (coerce-response? spec) (if (coerce-response? spec)
(coercion/-request-coercer this :response spec))))) (coercion/-request-coercer this :response spec)))
(-route-data-merge [this acc k v]
(impl/default-route-data-merge acc k v))))
(def coercion (create default-options)) (def coercion (create default-options))

View file

@ -176,8 +176,7 @@
(deftest merge-data-test (deftest merge-data-test
(is (= {:view 'b (is (= {:view 'b
:controllers [1 2]} :controllers [1 2]}
(impl/merge-data impl/default-route-data-merge (impl/merge-data "/"
"/"
[[:view 'a] [[:view 'a]
[:controllers [1]] [:controllers [1]]
[:view 'b] [:view 'b]
@ -185,8 +184,7 @@
(is (= {:view 'b (is (= {:view 'b
:controllers [2]} :controllers [2]}
(impl/merge-data impl/default-route-data-merge (impl/merge-data "/"
"/"
[[:view 'a] [[:view 'a]
[:controllers [1]] [:controllers [1]]
[:view 'b] [:view 'b]
@ -194,8 +192,7 @@
(is (= {:a schema/Str (is (= {:a schema/Str
:b schema/Str} :b schema/Str}
(-> (impl/merge-data rcm/route-data-merge (-> (impl/merge-data "/"
"/"
[[:parameters {:path {:a schema/Str}}] [[:parameters {:path {:a schema/Str}}]
[:parameters {:path {:b schema/Str}}]]) [:parameters {:path {:b schema/Str}}]])
:parameters :parameters
@ -204,9 +201,9 @@
(is (= [:map (is (= [:map
[:a 'string?] [:a 'string?]
[:b 'int?]] [:b 'int?]]
(-> (impl/merge-data rcm/route-data-merge (-> (impl/merge-data "/"
"/" [[:coercion rcm/coercion]
[[:parameters {:path [:map [:a 'string?]]}] [:parameters {:path [:map [:a 'string?]]}]
[:parameters {:path [:map [:b 'int?]]}]]) [:parameters {:path [:map [:b 'int?]]}]])
:parameters :parameters
:path :path