malli

https://github.com/metosin/malli :malli:
ikitommi 2020-06-08T06:44:18.007300Z

first class :string coming up:

(m/validate :string "")
; => true

(m/validate [:string {:min 1}] "")
; => false

(json-schema/transform [:string {:min 1, :max 4}])
; => {:type "string", :minLength 1, :maxLenght 4}

(mg/sample [:string {:min 1, :max 4}])
; => ("RMmR" "5" "oL" "G7" "ENo" "cAh" "iOb" "jG" "l8" "kuo")

(-> [:map
     [:a :string]
     [:b [:string {:min 1}]]
     [:c [:string {:max 4}]]
     [:d [:string {:min 1, :max 4}]]]
    (m/explain
      {:a 123
       :b ""
       :c "invalid"
       :d ""})
    (me/humanize))
;{:a ["should be string"],
; :b ["should be at least 1 characters"],
; :c ["should be at most 4 characters"],
; :d ["should be between 1 and 4 characters"]}

👍 3
🎉 2
ikitommi 2020-06-08T07:08:32.007500Z

https://github.com/metosin/malli/pull/205

naomarik 2020-06-08T07:37:01.007900Z

Perfect. I accidentally had a string? predicate in my spec awhile ago allowing unbounded inputs.

pithyless 2020-06-08T09:41:32.008400Z

@ikitommi any chance for a blank? option? Or is that too specific to add to malli-core? It's the first thing I have to add to all my string specs, since you almost never want to allow user input of just blank characters. In a similar vein, do you think malli-core generator should be using char-alphanumeric or simply string? I understand the first gives you nicer looking example data, but the second is more useful in testing edge cases.

pithyless 2020-06-08T10:06:01.008600Z

On second thought, the latter question is probably not worth the hassle (and one can always write a custom gen where it's needed). But still curious about a possibility of blank? or present? option.

pithyless 2020-06-08T10:07:31.008800Z

I moved my question to the PR, where it is probably more appropriate.

👍 1
ikitommi 2020-06-09T06:43:45.012400Z

@pithyless chaned the generator to char & string.

ikitommi 2020-06-08T18:50:15.009700Z

Example string-trimmer here too:

(require '[malli.transform :as mt])
(require '[malli.core :as m])
(require '[clojure.string :as str])

(defn string-trimmer []
  (mt/transformer
    {:decoders
     {:string
      {:compile (fn [schema _]
                  (let [{:string/keys [trim]} (m/properties schema)]
                    (when trim #(cond-> % (string? %) str/trim))))}}}))

(m/decode [:string {:min 1}] "    " string-trimmer)
; => "    "

(m/decode [:string {:string/trim true, :min 1}] "    " string-trimmer)
; => ""

(m/decoder :string string-trimmer)
; => #object[clojure.core$identity] ... no-op! :)