@dcj there is poor man's documentation about that change in CHANGELOG. The m/children
returns the [key properties schema]
tuple3s, so just use that instead. The new m/entries
(renamed iit so it's not a silent/evil breakage) is needed to effectively use the entry properties in schema applications like value transformation and schema transformations.
there is a long discussion about the options and the second in the related issue (https://github.com/metosin/malli/pull/212) and it's also documented in docstrings now: https://github.com/metosin/malli/blob/master/src/malli/core.cljc#L1127-L1155
Morning - I've been using Malli for the last few month. Last night when compiling my code lein pulled down a new version. I now get a failure when trying to compile my project Exception in thread "main" Syntax error compiling at (malli/core.cljc:1164:1).
I pulled down an earlier version of my project but in case I'd done something daft but still get the same problem. Has anyone else experienced this issue? cheers.
@shortlyportly i can reproduce. the new dynaload works differently (better!), will fix that.
@ikitommi - awesome - many thanks.
@shortlyportly should be fixed in master & [metosin/malli "0.0.1-20200924.063109-27"]
, ping @sergey.tkachenko too.
also, sci is now loaded when it’s first used. Using preload (cljs) or direct require (cljs, graalvm, jvm) makes it eager. But: having sci on classpath and not needing it, means it wont get loaded by malli, yielding faster startup time:
(time (require '[malli.core :as m]))
"Elapsed time: 466.76624 msecs"
=> nil
(time (m/eval "(+ 1 1)"))
"Elapsed time: 1591.515317 msecs"
=> 2
(time (m/eval "(+ 1 1)"))
"Elapsed time: 0.587728 msecs"
=> 2
(time (m/eval "(+ 1 1)"))
"Elapsed time: 0.772357 msecs"
=> 2
when clj command line tooling 3rd party library aot caching works, this can be made eager again.
@ikitommi - thank you - seems to be back and working. cheers
Next change, m/fn-schema
went away?
How should I change the below....
(def registry
(merge (m/predicate-schemas)
(m/class-schemas)
(m/comparator-schemas)
(m/base-schemas)
{:zoned-date-time (m/fn-schema :zoned-date-time #'zoned-date-time?)
:local-date (m/fn-schema :local-date #'local-date?)}))
@dcj there were 4 variants of the same thing, fn-schema
, leaf-schema
, predicate-schema
, partial-predicate-schena
, all replaced by m/-simple-schema
. Also, there is way to reset the default registry now. But the schema:
(m/-simple-schema {:type :local-date, :pred #'local-date?})
it also give you a way to read the schema properties and use them for the validation or transformation:
(def Date
(m/-simple-schema
(fn [{:keys [format type min]} children]
;; check props and children here, at schema instance creation time
(let [string->date (create-formatter-somehow format)
min-date (string->date min]
{:type :local-date
:pred (fn [x] (and (instance? type x) (check-that-is-greater-than min))
:type-properties {:decode/string string->date
:error/message {:en "should be date"}
:gen/gen generator-for-date}})))
(def LocalDateThisYear
[Date {:format "YYYY-MM-DD", :min "2020-01-01", :type java.time.LocalDate}])
(m/validate LocalDateThisYear #time/local-date "2020-12-12") ; => true
(m/decode LocalDateThisYear "2020-12-12" mt/string-decoder) ; => #time/local-date "2020-12-12"
(def registry
(merge (m/-predicate-schemas)
(m/-class-schemas)
(m/-comparator-schemas)
(m/-base-schemas)
(m/-type-schema) ;; <--- new too
{:zoned-date-time (m/-simple-schema {:type :zoned-date-time, :pred #'zoned-date-time?})
:local-date (m/-simple-schema {:type :local-date, :pred #'local-date?})}))
@ikitommi: Thank you for all this help/context/insight!
added tests and merged the lazy registries & lazy multi. Here’s the final api:
(def registry
(mr/lazy-registry
(m/default-schemas)
(fn [type registry]
;; simulates pulling CloudFormation Schemas when needed
(let [lookup {"AWS::ApiGateway::UsagePlan" [:map {:closed true}
[:Type [:= "AWS::ApiGateway::UsagePlan"]]
[:Description {:optional true} string?]
[:UsagePlanName {:optional true} string?]]
"AWS::AppSync::ApiKey" [:map {:closed true}
[:Type [:= "AWS::AppSync::ApiKey"]]
[:ApiId string?]
[:Description {:optional true} string?]]}]
(println "... loaded" type)
(some-> type lookup (m/schema {:registry registry}))))))
;; lazy multi, doesn't realize the schemas
(def CloudFormation
(m/schema
[:multi {:dispatch :Type, :lazy-refs true}
"AWS::ApiGateway::UsagePlan"
"AWS::AppSync::ApiKey"]
{:registry registry}))
(m/validate
CloudFormation
{:Type "AWS::ApiGateway::UsagePlan"
:Description "laiskanlinna"})
; ... loaded AWS::ApiGateway::UsagePlan
; => true
(m/validate
CloudFormation
{:Type "AWS::ApiGateway::UsagePlan"
:Description "laiskanlinna"})
; => true
Thank you!
has also the :multi
key spell-checker:
(deftest multi-error-test
(let [schema [:multi {:dispatch :type}
["plus" [:map [:value int?]]]
["minus" [:map [:value int?]]]]]
(is (= {:type ["invalid dispatch value"]}
(-> schema
(m/explain {:type "minuz"})
(me/humanize))))
(is (= {:type ["did you mean minus"]}
(-> schema
(m/explain {:type "minuz"})
(me/with-spell-checking)
(me/humanize))))))