This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-11
Channels
- # architecture (1)
- # babashka (61)
- # babashka-sci-dev (1)
- # beginners (85)
- # calva (112)
- # clj-kondo (279)
- # cljdoc (16)
- # cljs-dev (15)
- # cljsrn (7)
- # clojure (168)
- # clojure-europe (36)
- # clojure-nl (10)
- # clojure-spec (6)
- # clojure-uk (5)
- # clojured (1)
- # clojurescript (20)
- # core-async (16)
- # crypto (2)
- # cursive (13)
- # datomic (25)
- # events (7)
- # fulcro (21)
- # google-cloud (3)
- # graalvm (2)
- # graalvm-mobile (2)
- # gratitude (3)
- # helix (20)
- # honeysql (4)
- # hugsql (15)
- # introduce-yourself (15)
- # leiningen (2)
- # lsp (24)
- # luminus (22)
- # malli (21)
- # meander (11)
- # midje (1)
- # other-languages (1)
- # pathom (8)
- # re-frame (5)
- # reagent (5)
- # releases (2)
- # reveal (1)
- # shadow-cljs (18)
- # spacemacs (17)
- # sql (9)
- # tools-build (12)
- # tools-deps (4)
- # vim (12)
would this make sense? https://clojureverse.org/t/using-schema-like-schemas-in-malli/8613/2?u=ikitommi
Looks useful!
- a small step for people acquinted with Plumatic Schema to try Malli
- offers potentially a soft migration path from Schema to Malli. Assuming enough/all Schema predicates will be covered
- extend existing Schema code bases with the power of Malli (I believe :multi
will have better error reporting than schema.core/either
for instance). This again assumes that the translation of Schema will be near to perfect
(require '[malli.experimental.lite :as l])
(def Schema
(l/schema
{:map1 {:x int?
:y [:maybe string?]
:z (l/maybe keyword?)}
:map2 {:min-max [:int {:min 0 :max 10}]
:tuples (l/vector (l/tuple int? string?))
:optional (l/optional (l/maybe :boolean))
:set-of-maps (l/set {:e int?
:f string?})
:map-of-int (l/map-of int? {:s string?})}}))
;[:map
; [:map1
; [:map
; [:x int?]
; [:y [:maybe string?]]
; [:z [:maybe keyword?]]]]
; [:map2
; [:map
; [:min-max [:int {:min 0, :max 10}]]
; [:tuples [:vector [:tuple int? string?]]]
; [:optional {:optional true} [:maybe :boolean]]
18 lines of optional sugar, for simple cases like defining route parameters with reitit.
I can imagine this dsl would not cover complex cases of Malli, but sure looks useful to remove some boilerplate. Maybe it becomes confusing if these way of schema writing get mixed, not sure
yes, I would. not use this for anything βnormalβ, but for specific / inline cases, good: default reitit+malli:
:parameters {:query [:map
[:x int?]
[:y {:optional true} string?]]}
adding reitit+malli support for lite too:
:parameters {:query {:x int?, :y (l/optional string?)}}
I wanted to say maybe instead of supporting lite directly, asking the user to use to dsl themselves might lead to less confusion. But I see malli
can go into malli-lite
and malli-lite
can go into malli
:)
:parameters {:query {:x int?, :y (l/optional [:map-of string? string?]]}
Generates a valid malli schema, and also the other way around:
:parameters {:query [:map
[:x int?]
[:y {:optional true} (map-of string? string?]]}
Nice πͺSo that actually means complex cases are also covered, because normal malli can be used where necessary?
mostly, thinking about a good way to bring this together with malli, hopefully finding a lossless translation between the two. AsyncAPI looks like a very interesting way to solve the "schema problem" at an organizational level + all the metadata I would have had to reinvent the wheel to specify, which could go beyond interfacing with malli, but further code generation. You could derive reitit routes from it, and more
Today, when humanizing a value against a map schema, the error message "invalid type"
isn't super useful. I know I can add a custom error message. How could it be more descriptive?
(malli.error/humanize (malli.core/explain [:map] "string"))
;; => ["invalid type"]
Right, I know I can do that for a given schema, but wondered if maybe all maps could say something more specific.
oh woops sorry @U021RHDFFHN overlooked that you said that. I learned something, just tried this out and it works:
(malli.error/humanize
(malli.core/explain [:map] "string")
{:errors (-> default-errors
(assoc ::m/invalid-type
{:error/fn (fn [{:keys [value schema] :as in} _]
(str "The value you provided: '" value "' is not the correct type for the schema: '" (m/form schema) "'"))}))})
=> ["The value you provided: \"string\" is not the correct type for the schema: ':map'"]
the (m/form schema)
could be (m/type schema)
, just report on type, not whole form. otherwise, π―
Thanks! This works best for my use case:
(malli.error/humanize (malli.core/explain [:map] nil))
;; => ["invalid type"]
(malli.error/humanize
(malli.core/explain [:map [:hi string?]] nil)
{:errors (-> malli.error/default-errors
(assoc ::m/invalid-type
{:error/fn (fn [{:keys [_value schema]} _]
(str "The value provided does not conform to schema: '" (m/form #_m/type schema) "'"))}))})
;; => ["The value provided does not conform to schema: '[:map [:hi string?]]'"]