-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compose validation builders #63
Conversation
Thanks again for the contribution. I think it makes sense to first figure out what to do with #61 as this PR includes the same changes. Initial impression is that this simplifies a couple of things in the builder, which I am very glad about and really hope to see integrated. Also if this could help to solve #14 that would be much appreciated I also think the addition of an error type Maybe I am missing something? |
} | ||
|
||
interface ConstraintBuilder<C, T, E> { | ||
infix fun hint(hint: HintBuilder<C, T, E>) : ConstraintBuilder<C, T, E> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be possible to define an extension function to allow the old hint "error message"
in addition to hint stringHint("error message"
. Maybe stringHint
could be internal
.
infix fun <C,T> ConstraintBuilder<C,T,String>.hint(hint: String) = hint(stringHint(hint))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice one!
I added this extension function and one on ValidationBuilder
:
fun <C, T> ValidationBuilder<C, T, String>.addConstraint(hint: String, vararg values: Any, test: C.(T) -> Boolean): ConstraintBuilder<C, T, String>
I would keep stringHint
public. It provides the "templated" approach that was previously in the NodeValidation
. I can imagine that it is very useful when creating your own constraint extensions.
internal abstract fun <R> onEachArray(prop: KProperty1<T, Array<R>>, init: ValidationBuilder<R>.() -> Unit) | ||
infix fun <R> KProperty1<T, Iterable<R>>.onEach(init: ValidationBuilder<C, R, E>.() -> Unit) = onEachIterable(this.name, this, init) | ||
@JvmName("onEachIterable") | ||
infix fun <R> KFunction1<T, Iterable<R>>.onEach(init: ValidationBuilder<C, R, E>.() -> Unit) = onEachIterable(this.name, this, init) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This and the other extension functions on KFunction1
are not tested as far as I can see.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. I added some tests in a jvmTest module.
🤔 I think you are right about not being able to compose different types of errors yet. I'll check if there is some graceful solution for this. Just as in the other merge request; composition is only needed if one decides to mix different error types. If one sticks to the default (String) nothing changes. The way around this (used in this branch) is to include the As for #14, this is indeed solved in this branch, as we can now build validations on |
- add hint extension fn to ConstraintBuilder to support `hint "error message"` if E is String - add addConstraint to ValidationBuilder to support `addConstraint("string", .., ..)` if E is String
So I thought about the mapping between two error types and I think that it is not possible but not needed. Let me elaborate: since it is a custom error type we don't know what it is dependent of; e.g. an enum is dependent on nothing, but a custom error type could be dependent on
If the error type where we want to map away from is However, I think this is not needed. The constraint functions in Konform are all written in a way that they support the HintBuilder (and overloaded for the default String case). Anyone building its own constraint functions should either do it the same way or use their own custom type. So although we can add a map function argument to the Besides, there is a better alternative for using pre-build validations; constraint functions. |
This PR has a couple of problems:
I haven't looked in depth at the problems this PR tries to solve, but this is a bit more than I am willing to spend time on at the moment. Feel free to resubmit the PR(s) in smaller batches against the latest version or bring it up in an issue, so I can take a look again. |
This branch features a list of changes:
Composition of ValidationBuilders
Currently there is the use of something called
PropKey
to register builders. APropKey
contains aKProperty
and an enum value that explains what type ofValidation
to build. This is not really extensible.I refactored it to use the Composition pattern. A
ValidationBuilder
can be composed with another that adds an extra level of features.This was done so that in the future we can add different algebraic operators (think
oneOf
,lazy
,eager
, ...)Validation on Java functions
It also enables us to create validations on Java functions, because that is abstracted away in a
MappedValidationBuilder
that works allows us to switch from a validation over a typeT
to a typeV
where(T) -> V
.Custom error types
Now the errors are always strings. This is great in 99% of the cases, but in some cases I'd like to add some context to the error. Thus the error type is now generic.
The
static
function returns aHintBuilder
;Note the default error type is
String
, this means that almost no breaking changes were introduced.Required as Constraint
It was not possible to add a hint to the
required
validation (since it was noConstraint
).The composition pattern makes it easy to rebuild this. So now we can add a hint after a
required
block:or
Note the
with
function creates an object that combines a hint with aninit
function for aValidationBuilder
. This is the most noticeable breaking change.Improved type safety
To catch type errors on compile time instead runtime, a number of functions have improved type safety
Breaking changes
with
function for required builderValidationBuilder<A, B, C>
README
The readme is updated to reflect the latest changes, but needs some changes to elaborate on:
Extra notes on the changes
I know there are a lot of changes in this branch and understand that it is a lot to process in one go. I also believe that the essence of Konform is still intact, proven by the strong backwards compatibility.
Please consider merging this branch.