/
spec.cljc
44 lines (37 loc) · 1.35 KB
/
spec.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
(ns reitit.ring.spec
(:require [clojure.spec.alpha :as s]
[reitit.middleware :as middleware]
[reitit.spec :as rs]))
;;
;; Specs
;;
(s/def ::middleware (s/coll-of #(satisfies? middleware/IntoMiddleware %)))
(s/def ::data
(s/keys :req-un [::rs/handler]
:opt-un [::rs/name ::middleware]))
;;
;; Validator
;;
(defn merge-specs [specs]
(when-let [non-specs (seq (remove #(or (s/spec? %) (s/get-spec %)) specs))]
(throw
(ex-info
(str "Not all specs satisfy the Spec protocol: " non-specs)
{:specs specs
:non-specs non-specs})))
(s/merge-spec-impl (vec specs) (vec specs) nil))
(defn validate-route-data [routes key spec]
(->> (for [[p _ c] routes
[method {:keys [data] :as endpoint}] c
:when endpoint
:let [target (key endpoint)
mw-specs (seq (keep :spec target))
specs (keep identity (into [spec] mw-specs))
spec (merge-specs specs)]]
(when-let [problems (and spec (s/explain-data spec data))]
(rs/->Problem p method data spec problems)))
(keep identity) (seq)))
(defn validate-spec!
[routes {:keys [spec ::rs/explain] :or {explain s/explain-str, spec ::data}}]
(when-let [problems (validate-route-data routes :middleware spec)]
(rs/throw-on-problems! problems explain)))