It took a little while to figure this out by examining malli source, is this how you guys are passing in outside vars to the error/fn property?
(register! :phone [:re
{:description "Phone",
:phone-prefix-regex phone-prefix-regex
:phone-code-regex phone-code-regex
:error/fn
'(fn [{:keys [value schema]} _]
(let [{:keys [phone-prefix-regex
phone-code-regex]} (m/properties schema)
has-prefix? (re-find phone-prefix-regex value)
has-code? (re-find phone-code-regex value)]
(cond
(not has-prefix?)
:errors/phone-invalid-prefix
(not has-code?)
:errors/phone-invalid-country-code
:else
:errors/phone-invalid-number)))}
phone-regex])
Maybe would be helpful in the tips section 🙂
Actually this doesn't work in clojurescript. (m/properties schema)
returns #object[:cljs.coreMetaFn]
and don't know what to do with that.
I noticed (sci.core/eval-string "(inc 1)")
was returning the same MetaFn object and not 2
like the sci docs says it should. Just tried using the latest sci dependency and the error/fn works as expected. @ikitommi would you expect any issues using the latest sci with the current implementation of malli? Will do more testing on my end, I'm using the exact same validations for frontend and backend.
@naomarik I would expect latest sci works ok.
Also, if you define the validations as cljc code, e.g. no need to serialize over the wire, you can use plain functions instead of fn source code:
(defn valid? [x] (and (int? x) (> x 10)))
`(m/validate [:fn valid?] 11)
; => true`
Hey @ikitommi, I have all my malli specs in a cljc file, already. If I pass in functions instead of quoted functions, the clojurescript side won't through SCI will it? If that's the case will sci dependency get removed with advanced builds?
@ikitommi Sorry was being lazy about this didn't try it yet... Just tested myself and SCI adds about 0.5 megs to the (non gzipped) output and 93kb to the final JS output with gzip -9. I'm not sending code to be evalled as string in my project, is it cool if we make SCI an optional require?
I can try to do that myself but not sure how clean my solution would be compared to what you can come up with. Let me know what you think. I think I could also help with the docs to state that if sending functions over the wire is being used then SCI will be included for a heavier JS file.
I think this function
(defn ^:no-doc eval [?code]
(if (fn? ?code) ?code (sci/eval-string (str ?code) {:preset :termination-safe
:bindings {'m/properties properties
'm/name name
'm/children children
'm/map-entries map-entries}})))
if we conditionally require sci if the if test fails the fn?
check would be good.Just tried, conditional requires seem to not work, not sure what I was expecting requiring a library at runtime :)
there could also be an option to add custom bindings to sci, so one could use own fn's as part of the sci source code.
basically just merge to existing bindings https://github.com/metosin/malli/blob/master/src/malli/core.cljc#L878-L883
Yeah adding to the list of sci bindings would have been the most obvious thing to do for me . I saw it wasn't parameterized though so kept investigating. Actually I didn't try the error/fn
property without quoting it, passing in a function is a lot better in my use case. All the examples show quoted functions in the github page, so didn't think to try that.
Doc updates welcome