malli

Leena Hyvönen 2024-11-13T14:13:31.093859Z

How would this content dependent schema example go with a string property passed for compile? I always get :malli.core/child-error Below my last attempt, I stripped off a lot of keywords, but regardless if they are present or not, the result is always the same. What is missing from here?

(def EOkind
     (m/-simple-schema
      {:type `EOkind
       :compile (fn [_properties [kind] _options]
                  {:pred #(= (:kind %) kind)
                   :type-properties {:error/fn (fn [error _] (str "Kind should be " kind " , was " (:value error)))
                                     :decode/string mt/string-transformer}})}))

user=> (m/validate [EOkind "program"] {:id 2 :kind "program"})
Execution error (ExceptionInfo) at malli.core/-exception (core.cljc:138).
:malli.core/child-error

opqdonut 2024-11-14T05:56:42.306119Z

you need the :min and :max to tell malli what the minimum and maximum number of children is. the defaults are 0

opqdonut 2024-11-14T05:57:38.021169Z

user=> (def EOkind
  (m/-simple-schema
   {:type `EOkind
    :compile (fn [_properties [kind] _options]
               {:pred #(= (:kind %) kind)
                :min 1
                :max 1
                :type-properties {:error/fn (fn [error _] (str "Kind should be " kind " , was " (:value error)))
                                  :decode/string mt/string-transformer}})}))
#'user/EOkind
user=> (m/validate [EOkind "program"] {:id 2 :kind "program"})
true
user=> (m/validate [EOkind "program"] {:id 2 :kind "foo"})
false
this works for me!

opqdonut 2024-11-14T06:01:59.501679Z

if you don't have child schemas (something like [EOkind [:map [:foo :string]]] but just parameters to the schema, you can use the :property-pred functionality of -simple-schema like this:

user=> (def EOkind
  (m/-simple-schema
   {:type `EOkind
    :pred #(map? %)
    :property-pred (fn [props]
                     (fn [value]
                       (= (:kind value) (:kind props))))}))
#'user/EOkind
user=> (m/validate [EOkind {:kind "program"}] {:id 2 :kind "program"})
true
user=> (m/validate [EOkind {:kind "program"}] {:id 2 :kind "foo"})
false

opqdonut 2024-11-14T06:03:00.645969Z

you can still use :type-properties without :compile if you want to set the error-fn etc

Leena Hyvönen 2024-11-14T06:39:11.465349Z

Ahh, ok. Thank you again! 🙂