Fork me on GitHub
#malli
<
2020-09-24
>
ikitommi03:09:42

@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.

ikitommi04:09:40

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

thanks3 3
Dave Simmons05:09:54

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).

Dave Simmons05:09:40

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.

ikitommi06:09:13

@shortlyportly i can reproduce. the new dynaload works differently (better!), will fix that.

Dave Simmons06:09:33

@ikitommi - awesome - many thanks.

ikitommi06:09:58

@shortlyportly should be fixed in master & [metosin/malli "0.0.1-20200924.063109-27"], ping @sergey.tkachenko too.

ikitommi06:09:04

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

ikitommi06:09:59

when clj command line tooling 3rd party library aot caching works, this can be made eager again.

Dave Simmons07:09:20

@ikitommi - thank you - seems to be back and working. cheers

dcj16:09:20

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?)}))

ikitommi16:09:47

@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?})

ikitommi16:09:26

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"

ikitommi16:09: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?})}))

dcj16:09:05

@ikitommi: Thank you for all this help/context/insight!

ikitommi19:09:01

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

❤️ 6
ikitommi19:09:18

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))))))