Skip to content

Commit

Permalink
Merge pull request #6 from mvc-works/error-message
Browse files Browse the repository at this point in the history
trying for clearer failure message; alpha release
  • Loading branch information
soyaine authored Jan 24, 2020
2 parents 2a28d78 + 6f0f8b0 commit 403c171
Show file tree
Hide file tree
Showing 6 changed files with 1,079 additions and 515 deletions.
1,408 changes: 961 additions & 447 deletions calcit.cirru

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion meyvn.edn
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

{:pom {:group-id "mvc-works",
:artifact-id "lilac",
:version "0.0.2-a2",
:version "0.0.2-a4",
:name "Some validation functions"}
:packaging {:jar {:enabled true
:remote-repository {:id "clojars"
Expand Down
142 changes: 79 additions & 63 deletions src/lilac/core.cljs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@

(ns lilac.core (:require-macros [lilac.core]) (:require [lilac.util :refer [re?]]))
(ns lilac.core
(:require-macros [lilac.core])
(:require [lilac.util :refer [re?]]
[lilac.util :refer [preview-data]]
[clojure.string :as string]
[clojure.set :refer [difference]]))

(declare validate-set)

Expand Down Expand Up @@ -34,7 +39,7 @@
(defn format-message [acc result]
(if (nil? result)
acc
(let [message (str (remove symbol? (:coord result)) " - " (:message result))]
(let [message (str (:message result) " at " (vec (remove symbol? (:coord result))))]
(recur (str acc (if (some? acc) "\n" "") message) (:next result)))))

(defn validate-boolean [data rule coord]
Expand All @@ -44,7 +49,8 @@
:data data,
:rule rule,
:coord (conj coord 'boolean),
:message (get-in rule [:options :message] "Not a boolean")}))
:message (or (get-in rule [:options :message])
(str "expects a boolean, got " (preview-data data)))}))

(defn validate-custom [data rule coord]
(let [method (:fn rule), next-coord (conj coord 'custom), result (method data rule coord)]
Expand All @@ -54,7 +60,9 @@
:data data,
:rule rule,
:coord next-coord,
:message (get-in rule [:options :message] "Failed to validate with custom method")})))
:message (or (get-in rule [:options :message])
"failed to validate with custom method"),
:next result})))

(defn validate-fn [data rule coord]
(let [next-coord (conj coord 'fn)]
Expand All @@ -64,7 +72,8 @@
:data data,
:rule rule,
:coord next-coord,
:message (get-in rule [:options :message] "Not a function")})))
:message (or (get-in rule [:options :message])
(str "expects a function, got " (preview-data data)))})))

(defn validate-is [data rule coord]
(let [coord (conj coord 'is)]
Expand All @@ -74,7 +83,12 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Values not equal")})))
:message (or (get-in rule [:options :message])
(str
"expects just "
(preview-data (:item rule))
", got "
(preview-data data)))})))

(defn validate-keyword [data rule coord]
(let [next-coord (conj coord 'keyword)]
Expand All @@ -84,7 +98,8 @@
:data data,
:rule rule,
:coord next-coord,
:message (get-in rule [:options :message] "Not a keyword")})))
:message (or (get-in rule [:options :message])
(str "expects a keyword, got " (preview-data data)))})))

(defn validate-nil [data rule coord]
(let [next-coord (conj coord 'nil)]
Expand All @@ -94,7 +109,8 @@
:data data,
:rule rule,
:coord next-coord,
:message (get-in rule [:options :message] "Expects a nil")})))
:message (or (get-in rule [:options :message])
(str "expects a nil, got " (preview-data data)))})))

(defn validate-number [data rule coord]
(let [coord (conj coord 'number), min-v (:min rule), max-v (:max rule)]
Expand All @@ -106,12 +122,14 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Number not in range")})
:message (or (get-in rule [:options :message])
(str "expects number not in the range, got " (preview-data data)))})
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a number")})))
:message (or (get-in rule [:options :message])
(str "expects a number, got " (preview-data data)))})))

(defn validate-re [data rule coord]
(let [coord (conj coord 're)]
Expand All @@ -121,7 +139,8 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a regular expression")})))
:message (or (get-in rule [:options :message])
(str "expects a regular expression, got " (preview-data data)))})))

(defn validate-string [data rule coord]
(let [coord (conj coord 'string), re (:re rule)]
Expand All @@ -133,13 +152,15 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not passing regular expression")})
:message (or (get-in rule [:options :message])
(str "expects a string in " re ", got " (preview-data data)))})
{:ok? true})
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a string")})))
:message (or (get-in rule [:options :message])
(str "expected a string, but got " (preview-data data)))})))

(defn validate-symbol [data rule coord]
(let [coord (conj coord 'symbol)]
Expand All @@ -149,7 +170,8 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a symbol")})))
:message (or (get-in rule [:options :message])
(str "expects a symbol, got " (preview-data data)))})))

(defn validate-vector [data rule coord]
(let [item-rule (:item rule), coord (conj coord 'vector)]
Expand All @@ -160,19 +182,13 @@
(let [x0 (first xs)
child-coord (conj coord idx)
result (validate-lilac x0 item-rule child-coord)]
(if (:ok? result)
(recur (rest xs) (inc idx))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Invalid child in vector"),
:next result}))))
(if (:ok? result) (recur (rest xs) (inc idx)) result))))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a vector")})))
:message (or (get-in rule [:options :message])
(str "expects a vector, got " (preview-data data)))})))

(defn validate-set [data rule coord]
(let [item-rule (:item rule), coord (conj coord 'set)]
Expand All @@ -183,31 +199,27 @@
(let [x0 (first xs)
child-coord (conj coord idx)
result (validate-lilac x0 item-rule child-coord)]
(if (:ok? result)
(recur (rest xs) (inc idx))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Invalid item in set"),
:next result}))))
(if (:ok? result) (recur (rest xs) (inc idx)) result))))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a list")})))
:message (or (get-in rule [:options :message])
(str "expects a set, got " (preview-data data)))})))

(defn validate-or [data rule coord]
(let [items (:items rule), next-coord (conj coord 'or)]
(loop [xs items]
(loop [xs items, branches []]
(if (empty? xs)
{:ok? false,
:coord next-coord,
:rule rule,
:data data,
:message (get-in rule [:options :message] "Found no match in or")}
:message (get-in rule [:options :message] "found no matched case in \"or\""),
:branches branches,
:next (peek branches)}
(let [r0 (first xs), result (validate-lilac data r0 next-coord)]
(if (:ok? result) result (recur (rest xs))))))))
(if (:ok? result) result (recur (rest xs) (conj branches result))))))))

(defn validate-optional [data rule coord]
(let [item (:item rule), coord (conj coord 'optional)]
Expand All @@ -220,32 +232,37 @@
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Expects a inverted value in \"not\""),
:message (get-in rule [:options :message] "expects a inverted value in \"not\""),
:next result}
{:ok? true})))

(defn validate-map [data rule coord]
(let [coord (conj coord 'map), pairs (:pairs rule)]
(let [coord (conj coord 'map), pairs (:pairs rule), restricted-keys (:restricted-keys rule)]
(if (map? data)
(loop [xs pairs]
(if (empty? xs)
{:ok? true}
(let [[k0 r0] (first xs)
child-coord (conj coord k0)
result (validate-lilac (get data k0) r0 child-coord)]
(if (:ok? result)
(recur (rest xs))
{:ok? false,
:data (get data k0),
:rule r0,
:coord child-coord,
:message (str "field " (str k0) " not validated"),
:next result}))))
(if (or (nil? restricted-keys)
(and (set? restricted-keys)
(every? (fn [x] (contains? restricted-keys x)) (keys data))))
(loop [xs pairs]
(if (empty? xs)
{:ok? true}
(let [[k0 r0] (first xs)
child-coord (conj coord k0)
result (validate-lilac (get data k0) r0 child-coord)]
(if (:ok? result) (recur (rest xs)) result))))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (or (get-in rule [:options :message])
(let [existed-keys (set (keys data))
extra-keys (difference existed-keys restricted-keys)]
(str "unexpected keys in map " extra-keys)))})
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a map")})))
:message (or (get-in rule [:options :message])
(str "expects a map, got " (preview-data data)))})))

(defn validate-list [data rule coord]
(let [item-rule (:item rule), coord (conj coord 'list)]
Expand All @@ -256,19 +273,13 @@
(let [x0 (first xs)
child-coord (conj coord idx)
result (validate-lilac x0 item-rule child-coord)]
(if (:ok? result)
(recur (rest xs) (inc idx))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Invalid field in map"),
:next result}))))
(if (:ok? result) (recur (rest xs) (inc idx)) result))))
{:ok? false,
:data data,
:rule rule,
:coord coord,
:message (get-in rule [:options :message] "Not a list")})))
:message (or (get-in rule [:options :message])
(str "expects a list, got " (preview-data data)))})))

(defn validate-lilac
([data rule] (validate-lilac data rule []))
Expand Down Expand Up @@ -307,7 +318,8 @@
:coord next-coord,
:rule rule,
:data data,
:message (get-in rule [:options :message] "No more candidates")}))))))
:message (get-in rule [:options :message] "failed validating in \"and\""),
:next result}))))))

(def core-methods
{:boolean validate-boolean,
Expand Down Expand Up @@ -346,7 +358,11 @@

(defn map+
([pairs] (map+ pairs nil))
([pairs options] {:lilac-type :map, :pairs pairs, :options options}))
([pairs options]
{:lilac-type :map,
:pairs pairs,
:options options,
:restricted-keys (:restricted-keys options)}))

(defn nil+ ([] (nil+ {})) ([options] {:lilac-type :nil}))

Expand Down
18 changes: 15 additions & 3 deletions src/lilac/router.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@
is+
optional+]]))

(deflilac lilac-method+ () (optional+ (map+ {:type (is+ :file), :file (string+)})))
(deflilac
lilac-method+
()
(optional+
(map+
{:code (optional+ (number+)), :type (is+ :file), :file (string+)}
{:restricted-keys #{:code :type :file}})))

(deflilac
lilac-router-path+
Expand All @@ -31,9 +37,15 @@
:post (lilac-method+),
:put (lilac-method+),
:delete (lilac-method+),
:next (optional+ (vector+ (lilac-router-path+)))}))
:next (optional+ (vector+ (lilac-router-path+)))}
{:restricted-keys #{:path :get :post :put :delete :next}}))

(deflilac lilac-router+ () (map+ {:port (number+), :routes (vector+ (lilac-router-path+))}))
(deflilac
lilac-router+
()
(map+
{:port (number+), :routes (vector+ (lilac-router-path+))}
{:restricted-keys #{:port :routes}}))

(def router-data
{:port 7800,
Expand Down
10 changes: 9 additions & 1 deletion src/lilac/test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,15 @@
true
(validate-lilac
{:a 100, :b ["red" "blue"]}
(map+ {:a (number+), :b (vector+ (string+))} nil))))))
(map+ {:a (number+), :b (vector+ (string+))} nil)))))
(testing
"add restriction to keys"
(is
(=ok
false
(validate-lilac
{:a 100, :b ["red" "blue"]}
(map+ {:a (number+)} {:restricted-keys #{:a}}))))))

(deftest
test-nil
Expand Down
14 changes: 14 additions & 0 deletions src/lilac/util.cljs
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@

(ns lilac.util )

(defn preview-data [x]
(cond
(string? x) (pr-str x)
(boolean? x) (str x)
(number? x) (str x)
(keyword? x) (str x)
(symbol? x) (str "'" x)
(map? x) "a map"
(vector? x) "a vector"
(set? x) "a set"
(list? x) "a list"
(nil? x) "nil"
:else (str "Unknown(" (subs (str x) 0 10) ")")))

(def type-of-re (type #"x"))

(defn re? [x] (= type-of-re (type x)))

0 comments on commit 403c171

Please sign in to comment.