Fork me on GitHub
#fulcro
<
2024-03-28
>
pez14:03:32

Am I not supposed to use :merge in a guardrail? Something like [[:merge :any :map] :ret :any] gives me a malli invalid-schema error.

BUG: Internal error in Malli.

:malli.core/invalid-schema
#error {:message ":malli.core/invalid-schema", :data {:type :malli.core/invalid-schema, :message :malli.core/invalid-schema, :data {:schema :merge, :form [:merge :any :map]}}}
Although the form validates if I use malli to validate it. Like in the malli playground: https://malli.io/?value=%7B%3Aa%201%7D&amp;schema=%5B%3Amerge%20%3Aany%20%3Amap%5D

tony.kay16:03:06

I have no idea why that would be different between something you've seen on a Malli website. All guardrails does is call the same validate function you would. Perhaps it's a difference in the registry? Don't know. Perhaps ask on the malli channel?

tony.kay16:03:40

@U9S6X97KQ can you think of anything in the transform of g-spec that could corrupt this?

gnl17:03:18

Nope, looks good to me, and from the error message it looks like the schema is passed through to Malli unmolested. @U0ETXRFEW – can you paste the exact >defn and the output of (macroexpand '(>defn ...)) here to confirm?

gnl17:03:26

Could it be that there's a Malli version mismatch between http://malli.io and your environment, and your version of Malli doesn't support this?

gnl18:03:49

(On a side note, I'd recommend using => instead of :ret, especially with Malli, cause it's much more readable and easily distinguishable from Malli's keywords)

pez20:03:13

Ah, yes, it throws using malli directly too:

(comment
  (require '[malli.core :as m])
  (m/validate [:merge :map :map] {:name "World"})
  ; #error {:message ":malli.core/invalid- … ema {:schema :merge}" , :data {:type :malli.core/invalid-schema, :data {:schema :merge}}} {:type :repl/invoke, :name "<eval>", :js "malli.core.validate. … 77),"World"], null))" , :source "(m/validate [:merge … ap] {:name "World"})" , :source-map-json "{"version":3,↵ "file … name \"World\"})"]}↵" , …} 
  :rcf)
Not even with the same dependency coordinates as http://malli.io uses. I’ll take it to #CLDK6MFMK and see what gives.

pez20:03:53

Realized my mistake now. :mergeis from the malli.util schemas. Posted in the malli channel anyway: https://clojurians.slack.com/archives/CLDK6MFMK/p1711658048972759

pez20:03:12

Thanks for the side note, @U9S6X97KQ. I switched to the keyword because clojure-lsp/clj-kondo complaints that => remains unused, even though I use it. (And I also like using keywords instead of symbols wherever I get away with it) But I’ll check if I can fix the linter problem somehow.

pez22:03:52

Thanks for all help with my dabblings using Guardrails with #malli. I encoded what I have learnt (and a thing I still need to figure out) in a mini project: https://github.com/PEZ/guardrails-malli-mini

pez10:03:41

However, now I’m starting to worry that the project may be misleading people because of my poor understanding of the tools I’m holding. It seems Guardrails needs to be enabled in order for me to be able to use its registry for regular malli validations. Is that so or is there some option I should use to be able to use the registry without waking up the function instrumenting beast? Pasting the relevant code with my remarks about the issue, for context.

tony.kay12:03:14

Good question. The general intention is for the guardrails support to be removable at runtime in production. I'm not sure we're meeting that goal yet, but that is the goal. As such, I would think the desired pattern would be to create your data validations that you need at run time and put them in one registry, and then merge that registry with the guardrails registry if you also need those data validations there. Overall this goal is more targeted at clojurescript, so perhaps we should be making better leverage of goog.DEBUG Or something.

pez13:03:55

Thanks. I am creating my validations at runtime. Just that I am using the >def macro for it. But that is not intended to work when Guardrails is disabled, I take it? So in my case it’s better to maintain my own registry and make both malli and Guardrails use it?

tony.kay13:03:20

Um…I’d have to look but I think there’s a way to ask to keep specs without keeping GR instrumentation…if not, it’s an intended feature…been a while since I worked on that angle and it might have gotten missed for Malli

tony.kay14:03:39

Ah, funny enough, the clojure spec stuff does not go away, but the malli stuff does 😄

tony.kay14:03:08

it’s quite inconsistent actually 😕

pez15:03:59

Thanks! I like that it is intended to work. 😃 I updated the note like so now. Does it look fine to you?

;; To use the Guardrails' registry with Malli, one way is to specify it as a `:registry` option
  ;; NB: This currently only works if Guardrails is enabled.
  ;;     You may want to manage any schemas that you want to be able to
  ;;     validate using Malli directly in production builds separately.
  (require '[malli.core :as m])
  ;; The require doesn't allow me to use the alias in ClojureScript for some reason...
  (malli.core/validate [:merge :hello/contact [:map [:mood :int]]]
                       {:nom "World" :mood 42}
                       {:registry gr.reg/registry}) ;; => true

tony.kay15:03:12

The thing you could do is set Malli’s default registry to be mutable and have all of your things in it, and then reset GR’s registry to point back at that as well. Then your registry is the reference one. Then just copy the >def macro and have it modify your reference one instead, and use your version instead. Then your validations won’t need to specify a registry, and the Malli stuff will work in both always

pez16:03:11

How do I “reset GR’s registry to point back at” the mutable Malli registry?

tony.kay16:03:27

well, I guess you’d just merge the resultant app registry content into GR registry? Perhaps there should be a way to completely set the value of the GR registry…I mean, it’s a var, you can always alter-var-root 😄

pez16:03:06

I think I tried that some days ago and it didn’t work. Let me try again and see what gives…

tony.kay16:03:24

in cljs it is diff because there are no vars

tony.kay16:03:36

but you should be able to hack it with set! in that case I think (not 100% sure that’s great advice, but I admit I’ve done it 😄 )

pez16:03:45

I can’t reproduce whatever error I got last time I tried, so I probably just was doing something else funny then.

pez16:03:27

Though. About merging the resultant registry. Should I do that as part of my >def macro then? Since that would change the resultant registry every time it is used….

pez17:03:34

I think I have it working according to this alternative scheme now. My macro is only calling my register! function like so:

(defn register! [type ?schema]
  (swap! !registry assoc type ?schema)
  (gr.reg/merge-schemas! @!registry))


#?(:clj (defmacro >def [type schema]
          `(register! ~type ~schema)))
Is there a point with having it as a macro then? Seem my project can use register! directly, but I have a feeling I am missing something…

pez17:03:03

I’ve updated the example project now. Would be wonderful if you scrutinzed the README info and the notes in the implementation files. I’d like to not be spreading misinformation. 😃

tony.kay19:03:25

The only reason we make it a macro is so it can read the configuration in cljs (the browser has no access to the compile-time environment)