/
core.cljc
150 lines (112 loc) · 4.22 KB
/
core.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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
(ns com.ben-allred.formation.core
(:refer-clojure :exclude [identity])
(:require
[com.ben-allred.formation.validations :as v]
[com.ben-allred.formation.transformations :as t]))
;; Validations
(defn validator
"Create a validating function from a configuration.
(validator {:a (pred number? \"must be a number\") :b (required \"required\")}"
[config]
(v/validator config))
(defn required
"Creates a validator that produces a msg when a value is nil.
(required \"this is required\")"
[msg]
(v/required msg))
(defn pred
"Creates a validator that produces a msg when a value does not satisfy the predicate.
Does not validate nil.
(pred string? \"needs to be a string\")"
[p msg]
(v/pred p msg))
(defn identity
"Creates a validator that produces a msg when the value does not equal the result of
passing the value through the identity function. Does not validate nil.
(identity sort \"must be sorted\")"
[f msg]
(v/pred #(= % (f %)) msg))
(defn matches
"Creates a validator that produces a msg when the value does not match a given regular
expression or the value is not a string. Does not validate nil.
(matches #\"[0-9]{4,}\" \"at least 4 digits\")"
[re msg]
(v/pred (partial re-matches re) msg))
(defn min-length
"Creates a validator that produces a msg when the length of the value is not at least
what is specified. Does not validate nil.
(min-length 10 \"must be at least 10\")"
[n msg]
(v/pred (comp #(>= % n) count) msg))
(defn max-length
"Creates a validator that produces a msg when the length of the value is not at least
what is specified. Does not validate nil.
(max-length 10 \"must be at most 10\")"
[n msg]
(v/pred (comp #(<= % n) count) msg))
(defn hydrate
"Creates a validator that hydrates the stored value for validation.
(let [validator (hydrate widget-id->widget widget-validator)]
(validator widget-id))"
[hydrator config]
(comp (validator config) hydrator))
(defn whenp
"Predicate the usage of a validator config spec. The predicate is called with the same
args as the validator.
(def validator (whenp < (pred (fn [lesser greater] (< (- greater lesser) 10))
\"Second must be within 10 of first\")))
(validator 100 1)
;;=> nil
(validator 1 5)
;;=> nil
(validator 1 100)
;;=> [\"Second must be within 10 of first\"]"
[pred config]
(let [v (validator config)]
(fn [value & args]
(when (apply v/affirm pred value args)
(apply v value args)))))
;; Transformations
(defn transformer
"Creates a transforming function that transforms a value through a data config.
(transformer {:person {:email string/lower-case :attributes ^::map-of {keyword str}}})"
[config]
(t/transformer config))
(defn when-somep
"Utility wrapper for transforming functions that you only want called when the
value is not nil (i.e. not required).
(make-transformer {:something [(when-somep string/trim) (when-somep string/upper-case)]})"
[p]
(fn [value]
(when (some? value)
(p value))))
;; Deprecated
(defn ^:deprecated make-validator
"Deprecated. Use `validator` instead."
[config]
(validator config))
(defn ^:deprecated validator-map
"Deprecated. Use ::map-of metadata instead.
(validator ^::map-of {[(required \"required\") (pred keyword? \"keyword\")] val-validator})"
[key-config val-config]
(validator ^::map-of {key-config val-config}))
(defn ^:deprecated validator-coll
"Deprecated. Use ::coll-of metadata instead.
(validator ^::coll-of [[(required \"required\") (pred string? \"string\")]])"
[config]
(validator ^::coll-of [config]))
(defn ^:deprecated validator-tuple
"Deprecated. Use ::tuple-of metadata instead.
(validator ^::tuple-of [(pred number? \"number\") [(required \"required\") (matches #\"[0-9]{4,}\" \"digits\")]])"
[& configs]
(validator (with-meta (vec configs) {::tuple-of true})))
(defn ^:deprecated make-transformer
"Deprecated. Use `transformer` instead."
[config]
(transformer config))
(defn ^:deprecated ifn->fn
"Deprecated. Use ::ifn metadata instead.
Utility wrapper for maps when you want to use them as a transforming function
because make-transformer treats maps as nested transformations."
[ifn]
(with-meta ifn {::ifn true}))