Skip to content

Commit

Permalink
Open up ValidationBuilder for extension (#170)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhoepelman authored Nov 15, 2024
1 parent 6ec40a4 commit 15b871b
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
12 changes: 9 additions & 3 deletions api/konform.api
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ public final class io/konform/validation/Invalid : io/konform/validation/Validat
public fun getErrors ()Ljava/util/List;
public fun hashCode ()I
public fun isValid ()Z
public synthetic fun prependPath$konform (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult;
public synthetic fun prependPath$konform (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult;
public fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/Invalid;
public synthetic fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult;
public fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/Invalid;
public synthetic fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult;
public fun toString ()Ljava/lang/String;
}

Expand All @@ -52,6 +54,8 @@ public final class io/konform/validation/Valid : io/konform/validation/Validatio
public final fun getValue ()Ljava/lang/Object;
public fun hashCode ()I
public fun isValid ()Z
public fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult;
public fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult;
public fun toString ()Ljava/lang/String;
}

Expand All @@ -73,7 +77,7 @@ public final class io/konform/validation/Validation$DefaultImpls {
public static fun prependPath (Lio/konform/validation/Validation;Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/Validation;
}

public final class io/konform/validation/ValidationBuilder {
public class io/konform/validation/ValidationBuilder {
public static final field Companion Lio/konform/validation/ValidationBuilder$Companion;
public fun <init> ()V
public final fun addConstraint (Ljava/lang/String;[Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lio/konform/validation/Constraint;
Expand Down Expand Up @@ -154,6 +158,8 @@ public abstract class io/konform/validation/ValidationResult {
public abstract fun isValid ()Z
public final fun map (Lkotlin/jvm/functions/Function1;)Lio/konform/validation/ValidationResult;
public final fun plus (Lio/konform/validation/ValidationResult;)Lio/konform/validation/ValidationResult;
public abstract fun prependPath (Lio/konform/validation/path/PathSegment;)Lio/konform/validation/ValidationResult;
public abstract fun prependPath (Lio/konform/validation/path/ValidationPath;)Lio/konform/validation/ValidationResult;
}

public final class io/konform/validation/ValidationResultKt {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import kotlin.reflect.KProperty1
private annotation class ValidationScope

@ValidationScope
public class ValidationBuilder<T> {
// Class is open to users can define their extra local extension methods
public open class ValidationBuilder<T> {
private val constraints = mutableListOf<Constraint<T>>()
private val subValidations = mutableListOf<Validation<T>>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public sealed class ValidationResult<out T> {
}
}

internal abstract fun prependPath(pathSegment: PathSegment): ValidationResult<T>
public abstract fun prependPath(pathSegment: PathSegment): ValidationResult<T>

internal abstract fun prependPath(path: ValidationPath): ValidationResult<T>
public abstract fun prependPath(path: ValidationPath): ValidationResult<T>
}

public data class Invalid(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.konform.validation.validationbuilder

import io.konform.validation.Validation
import io.konform.validation.ValidationBuilder
import io.konform.validation.ValidationError
import io.konform.validation.constraints.minLength
import io.konform.validation.path.ValidationPath
import io.kotest.assertions.konform.shouldBeInvalid
import io.kotest.assertions.konform.shouldBeValid
import io.kotest.assertions.konform.shouldContainExactlyErrors
import kotlin.reflect.KProperty1
import kotlin.test.Test

class ExtendingValidationBuilderTest {
@Test
fun allowsExtending() {
val validation =
MyValidationBuilder<User> {
User::name trimmed {
minLength(1)
}
}

validation shouldBeValid User("John")
(validation shouldBeInvalid User("")).shouldContainExactlyErrors(
ValidationError.of(User::name, "must have at least 1 characters"),
)
(validation shouldBeInvalid User("\t")).shouldContainExactlyErrors(
ValidationError.of(User::name, "must have at least 1 characters"),
)
}
}

data class User(
val name: String,
)

class MyValidationBuilder<T> : ValidationBuilder<T>() {
infix fun KProperty1<T, String>.trimmed(init: ValidationBuilder<String>.() -> Unit): Unit =
this {
validate(ValidationPath.EMPTY, { it.trim() }) {
run(buildWithNew(init))
}
}

companion object {
operator fun <T> invoke(init: MyValidationBuilder<T>.() -> Unit): Validation<T> {
val builder = MyValidationBuilder<T>()
init(builder)
return builder.build()
}
}
}

0 comments on commit 15b871b

Please sign in to comment.