Full code example:
But if I use `(s/def :foo/email (s/and ::common-email))` instead it return
(s/def :foo/email ::common-email)
:via [:db/foo :foo/email :api.foo/common-email]
What happen here?
[:db/foo :api.foo/common-email] vs [:db/foo :foo/email :api.foo/common-email]
So (s/def :foo/email ::common-email) is totally omit here. In my opinion it is a bug, not a feature
Why is it important to fix?
It is important to keep it full tracked to turn this errors to right communication in User Interface.
So `[:db/foo :foo/email :api.foo/common-email]`, I am looking if I have proper message for UI. First `:api.foo/common-email`. No message, then check `:foo/email`. I have message for it so I can return "E-mail is not valid".
In practice it can be `:user/password` with split spec for length, special characters etc. validation or `:company/vat-id` based on country. But always I don't want to keep final validation at that moment, because things like street, phone number, vat-id, email etc. are common and I want to have one definition in one place.
On top of it I can do for example `(s/def :user/email (s/and (s/conformer clojure.string/lower-case) ::s-common/email))`. Here is the point. But not all e-mail validations will do lower-case. So today I have to use dirty hack or have redundant e-mail validation in all places which is harder to maintenance.
I don't want to base on `::common-email`, because this part is considered to change in any moment. It can be bookkeeping library with common definition for European Union vat-id. I don't want to base messages for UI for this library, I want to base on my definitions in my code, but `(s/def :company/vat-id ::bookkeeping-library/vat-id)` lose in `:via`.
We can imagine it is deeper and more complex structure. At that moment figuring out what is the issue of fail is rocket science, that is why I use dirty hack `(s/def :foo/email (s/and ::common-email))` to read it simple from `:via`.