-
Notifications
You must be signed in to change notification settings - Fork 250
/
spec.cljc
54 lines (47 loc) · 1.57 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
45
46
47
48
49
50
51
52
53
54
(ns reitit.ring.spec
(:require [clojure.spec.alpha :as s]
[reitit.exception :as exception]
[reitit.middleware :as middleware]
[reitit.spec :as rs]))
;;
;; Specs
;;
(s/def ::middleware (s/coll-of #(satisfies? middleware/IntoMiddleware %) :kind vector?))
(s/def ::get map?)
(s/def ::head map?)
(s/def ::post map?)
(s/def ::put map?)
(s/def ::delete map?)
(s/def ::connect map?)
(s/def ::options map?)
(s/def ::trace map?)
(s/def ::patch map?)
(s/def ::data
(s/keys :opt-un [::rs/handler ::rs/name ::rs/no-doc ::middleware]))
;;
;; Validator
;;
(defn merge-specs [specs]
(when-let [non-specs (seq (remove #(or (s/spec? %) (s/get-spec %)) specs))]
(exception/fail!
::invalid-specs
{:specs specs
:invalid non-specs}))
(s/merge-spec-impl (vec specs) (vec specs) nil))
(defn validate-route-data [routes key wrap spec]
(->> (for [[p _ c] routes
[method {:keys [data] :as endpoint}] c
:when endpoint
:let [target (key endpoint)
component-specs (seq (keep :spec target))
specs (keep identity (into [spec] component-specs))
spec (wrap (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
[routes {:keys [spec ::rs/wrap] :or {spec ::data, wrap identity}}]
(when-let [problems (validate-route-data routes :middleware wrap spec)]
(exception/fail!
::rs/invalid-route-data
{:problems problems})))