Skip to content

Commit

Permalink
Move io.konform.validation.jsonschema to io.konform.validation.constr…
Browse files Browse the repository at this point in the history
…aints
  • Loading branch information
dhoepelman committed Nov 13, 2024
1 parent 44c25c0 commit ddf5133
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,33 @@ package io.konform.validation.constraints

import io.konform.validation.Constraint
import io.konform.validation.ValidationBuilder
import kotlin.jvm.JvmName

public fun <T> ValidationBuilder<Iterable<T>>.minItems(minSize: Int): Constraint<Iterable<T>> =
public fun <T : Iterable<*>> ValidationBuilder<T>.minItems(minSize: Int): Constraint<T> =
addConstraint("must have at least {0} items", minSize.toString()) { it.count() >= minSize }

@JvmName("arrayMinItems")
public fun <T> ValidationBuilder<Array<T>>.minItems(minSize: Int): Constraint<Array<T>> =
addConstraint("must have at least {0} items", minSize.toString()) { it.count() >= minSize }

public fun <T> ValidationBuilder<Iterable<T>>.maxItems(maxSize: Int): Constraint<Iterable<T>> =
public fun <T : Iterable<*>> ValidationBuilder<T>.maxItems(maxSize: Int): Constraint<T> =
addConstraint("must have at most {0} items", maxSize.toString()) {
it.count() <= maxSize
}

@JvmName("arrayMaxItems")
public fun <T> ValidationBuilder<Array<T>>.maxItems(maxSize: Int): Constraint<Array<T>> =
addConstraint("must have at most {0} items", maxSize.toString()) {
it.count() <= maxSize
}

public fun <T> ValidationBuilder<Iterable<T>>.uniqueItems(unique: Boolean): Constraint<Iterable<T>> =
public fun <T : Iterable<*>> ValidationBuilder<T>.uniqueItems(unique: Boolean = true): Constraint<T> =
addConstraint("all items must be unique") {
!unique || it.distinct().count() == it.count()
}

public fun <T> ValidationBuilder<Array<T>>.uniqueItems(unique: Boolean): Constraint<Array<T>> =
@JvmName("arrayUniqueItems")
public fun <T> ValidationBuilder<Array<T>>.uniqueItems(unique: Boolean = true): Constraint<Array<T>> =
addConstraint("all items must be unique") {
!unique || it.distinct().count() == it.count()
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public fun <K, V> ValidationBuilder<Map<K, V>>.minProperties(minSize: Int): Cons
public fun <K, V> ValidationBuilder<Map<K, V>>.maxProperties(maxSize: Int): Constraint<Map<K, V>> =
maxItems(maxSize) hint "must have at most {0} properties"

public fun <K, V> ValidationBuilder<Map<K, V>>.uniqueItems(unique: Boolean): Constraint<Map<K, V>> =
public fun <K, V> ValidationBuilder<Map<K, V>>.uniqueItems(unique: Boolean = true): Constraint<Map<K, V>> =
addConstraint("all items must be unique") {
!unique || it.values.distinct().count() == it.count()
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,65 +6,74 @@ import io.konform.validation.constraints.const as movedConst
import io.konform.validation.constraints.enum as movedEnum
import io.konform.validation.constraints.exclusiveMaximum as movedExclusiveMaximum
import io.konform.validation.constraints.exclusiveMinimum as movedExclusiveMinimum
import io.konform.validation.constraints.maxItems as movedMaxItems
import io.konform.validation.constraints.maxLength as movedMaxLength
import io.konform.validation.constraints.maxProperties as movedMaxProperties
import io.konform.validation.constraints.maximum as movedMaximum
import io.konform.validation.constraints.minItems as movedMinItems
import io.konform.validation.constraints.minLength as movedMinLength
import io.konform.validation.constraints.minProperties as movedMinProperties
import io.konform.validation.constraints.minimum as movedMinimum
import io.konform.validation.constraints.multipleOf as movedMultipleOf
import io.konform.validation.constraints.pattern as movedPattern
import io.konform.validation.constraints.type as movedType
import io.konform.validation.constraints.uniqueItems as movedUniqueItems
import io.konform.validation.constraints.uuid as movedUuid

@Deprecated("Moved to io.konform.validation.constraints", ReplaceWith("type()", "io.konform.validation.constraints.type"))
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("io.konform.validation.constraints.type<T>()", "io.konform.validation.constraints.type"),
)
public inline fun <reified T> ValidationBuilder<*>.type(): Constraint<*> = movedType<T>()

@Deprecated("Moved to io.konform.validation.constraints", ReplaceWith("enum(*allowed)", "io.konform.validation.constraints.enum"))
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("io.konform.validation.constraints.enum(*allowed)", "io.konform.validation.constraints.enum"),
)
public fun <T> ValidationBuilder<T>.enum(vararg allowed: T): Constraint<T> = movedEnum(*allowed)

@Deprecated("Moved to io.konform.validation.constraints", ReplaceWith("enum()", "io.konform.validation.constraints.enum"))
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("io.konform.validation.constraints.enum()", "io.konform.validation.constraints.enum"),
)
public inline fun <reified T : Enum<T>> ValidationBuilder<String>.enum(): Constraint<String> = movedEnum<T>()

@Deprecated("Moved to io.konform.validation.constraints", ReplaceWith("const(expected)", "io.konform.validation.constraints.const"))
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("io.konform.validation.constraints.const(expected)", "io.konform.validation.constraints.const"),
)
public fun <T> ValidationBuilder<T>.const(expected: T): Constraint<T> = movedConst(expected)

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("minLength(length)", imports = ["io.konform.validation.constraints.minLength"]),
ReplaceWith("io.konform.validation.constraints.minLength(length)", "io.konform.validation.constraints.minLength"),
)
public fun ValidationBuilder<String>.minLength(length: Int): Constraint<String> = movedMinLength(length)

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("maxLength(length)", imports = ["io.konform.validation.constraints.maxLength"]),
ReplaceWith("io.konform.validation.constraints.maxLength(length)", "io.konform.validation.constraints.maxLength"),
)
public fun ValidationBuilder<String>.maxLength(length: Int): Constraint<String> = movedMaxLength(length)

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("pattern(length)", imports = ["io.konform.validation.constraints.pattern"]),
ReplaceWith("pattern(length)", "io.konform.validation.constraints.pattern"),
)
public fun ValidationBuilder<String>.pattern(pattern: String): Constraint<String> = movedPattern(pattern)

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("uuid()", imports = ["io.konform.validation.constraints.uuid"]),
ReplaceWith("uuid()", "io.konform.validation.constraints.uuid"),
)
public fun ValidationBuilder<String>.uuid(): Constraint<String> = movedUuid()

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("pattern(pattern)", imports = ["io.konform.validation.constraints.pattern"]),
ReplaceWith("pattern(pattern)", "io.konform.validation.constraints.pattern"),
)
public fun ValidationBuilder<String>.pattern(pattern: Regex): Constraint<String> = movedPattern(pattern)

@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("multipleOf(factor)", imports = ["io.konform.validation.constraints.multipleOf"]),
ReplaceWith("multipleOf(factor)", "io.konform.validation.constraints.multipleOf"),
)
public fun <T : Number> ValidationBuilder<T>.multipleOf(factor: Number): Constraint<T> = movedMultipleOf(factor)

Expand Down Expand Up @@ -100,24 +109,33 @@ public fun <T : Number> ValidationBuilder<T>.exclusiveMinimum(minimumExclusive:
ReplaceWith("minItems(minSize)", "io.konform.validation.constraints.minItems"),
)
public inline fun <reified T> ValidationBuilder<T>.minItems(minSize: Int): Constraint<T> =
when (T::class) {
is Iterable<*> -> (this as ValidationBuilder<Iterable<*>>).movedMinItems(minSize) as Constraint<T>
is Array<*> -> (this as ValidationBuilder<Array<Any?>>).movedMinItems(minSize) as Constraint<T>
is Map<*, *> -> (this as ValidationBuilder<Map<Any?, *>>).movedMinItems(minSize) as Constraint<T>
else -> throw IllegalStateException("minItems can not be applied to type ${T::class}")
addConstraint(
"must have at least {0} items",
minSize.toString(),
) {
when (it) {
is Iterable<*> -> it.count() >= minSize
is Array<*> -> it.count() >= minSize
is Map<*, *> -> it.count() >= minSize
else -> throw IllegalStateException("minItems can not be applied to type ${T::class}")
}
}

@Suppress("UNCHECKED_CAST")
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("maxItems(maxSize)", "io.konform.validation.constraints.maxItems"),
)
public inline fun <reified T> ValidationBuilder<T>.maxItems(maxSize: Int): Constraint<T> =
when (T::class) {
is Iterable<*> -> (this as ValidationBuilder<Iterable<*>>).movedMaxItems(maxSize) as Constraint<T>
is Array<*> -> (this as ValidationBuilder<Array<Any?>>).movedMaxItems(maxSize) as Constraint<T>
is Map<*, *> -> (this as ValidationBuilder<Map<Any?, *>>).movedMaxItems(maxSize) as Constraint<T>
else -> throw IllegalStateException("maxItems can not be applied to type ${T::class}")
addConstraint(
"must have at most {0} items",
maxSize.toString(),
) {
when (it) {
is Iterable<*> -> it.count() <= maxSize
is Array<*> -> it.count() <= maxSize
is Map<*, *> -> it.count() <= maxSize
else -> throw IllegalStateException("maxItems can not be applied to type ${T::class}")
}
}

@Deprecated(
Expand All @@ -134,15 +152,18 @@ public fun <K, V> ValidationBuilder<Map<K, V>>.minProperties(minSize: Int): Cons
public fun <K, V> ValidationBuilder<Map<K, V>>.maxProperties(maxSize: Int): Constraint<Map<K, V>> =
movedMaxProperties(maxSize) hint "must have at most {0} properties"

@Suppress("UNCHECKED_CAST")
@Deprecated(
"Moved to io.konform.validation.constraints",
ReplaceWith("uniqueItems(unique)", "io.konform.validation.constraints.uniqueItems"),
)
public inline fun <reified T> ValidationBuilder<T>.uniqueItems(unique: Boolean): Constraint<T> =
when (T::class) {
is Iterable<*> -> (this as ValidationBuilder<Iterable<*>>).movedUniqueItems(unique) as Constraint<T>
is Array<*> -> (this as ValidationBuilder<Array<Any?>>).movedUniqueItems(unique) as Constraint<T>
is Map<*, *> -> (this as ValidationBuilder<Map<Any?, *>>).movedUniqueItems(unique) as Constraint<T>
else -> throw IllegalStateException("uniqueItems can not be applied to type ${T::class}")
addConstraint(
"all items must be unique",
) {
!unique ||
when (it) {
is Iterable<*> -> it.distinct().count() == it.count()
is Array<*> -> it.distinct().count() == it.count()
else -> throw IllegalStateException("uniqueItems can not be applied to type ${T::class}")
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package io.konform.validation

import io.konform.validation.jsonschema.minimum
import io.konform.validation.constraints.minimum
import io.konform.validation.types.EmptyValidation
import io.konform.validation.types.ValidateAll
import io.kotest.assertions.konform.shouldBeInvalid
Expand Down
14 changes: 7 additions & 7 deletions src/commonTest/kotlin/io/konform/validation/ReadmeExampleTest.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package io.konform.validation

import io.konform.validation.jsonschema.maxItems
import io.konform.validation.jsonschema.maxLength
import io.konform.validation.jsonschema.maximum
import io.konform.validation.jsonschema.minItems
import io.konform.validation.jsonschema.minLength
import io.konform.validation.jsonschema.minimum
import io.konform.validation.jsonschema.pattern
import io.konform.validation.constraints.maxItems
import io.konform.validation.constraints.maxLength
import io.konform.validation.constraints.maximum
import io.konform.validation.constraints.minItems
import io.konform.validation.constraints.minLength
import io.konform.validation.constraints.minimum
import io.konform.validation.constraints.pattern
import io.kotest.assertions.konform.shouldBeInvalid
import io.kotest.assertions.konform.shouldBeValid
import io.kotest.assertions.konform.shouldContainError
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
package io.konform.validation

import io.konform.validation.JSONSchemaStyleConstraintsTest.TCPPacket.ACK
import io.konform.validation.JSONSchemaStyleConstraintsTest.TCPPacket.SYN
import io.konform.validation.JSONSchemaStyleConstraintsTest.TCPPacket.SYNACK
import io.konform.validation.enum.enum
import io.konform.validation.jsonschema.const
import io.konform.validation.jsonschema.exclusiveMaximum
import io.konform.validation.jsonschema.exclusiveMinimum
import io.konform.validation.jsonschema.maxItems
import io.konform.validation.jsonschema.maxLength
import io.konform.validation.jsonschema.maxProperties
import io.konform.validation.jsonschema.maximum
import io.konform.validation.jsonschema.minItems
import io.konform.validation.jsonschema.minLength
import io.konform.validation.jsonschema.minProperties
import io.konform.validation.jsonschema.minimum
import io.konform.validation.jsonschema.multipleOf
import io.konform.validation.jsonschema.pattern
import io.konform.validation.jsonschema.type
import io.konform.validation.jsonschema.uniqueItems
import io.konform.validation.jsonschema.uuid
package io.konform.validation.constraints

import io.konform.validation.Valid
import io.konform.validation.Validation
import io.konform.validation.ValidationResult
import io.konform.validation.constraints.ConstraintsTest.TCPPacket.ACK
import io.konform.validation.constraints.ConstraintsTest.TCPPacket.SYN
import io.konform.validation.constraints.ConstraintsTest.TCPPacket.SYNACK
import io.konform.validation.constraints.const
import io.konform.validation.constraints.exclusiveMaximum
import io.konform.validation.constraints.exclusiveMinimum
import io.konform.validation.constraints.maxItems
import io.konform.validation.constraints.maxLength
import io.konform.validation.constraints.maxProperties
import io.konform.validation.constraints.maximum
import io.konform.validation.constraints.minItems
import io.konform.validation.constraints.minLength
import io.konform.validation.constraints.minProperties
import io.konform.validation.constraints.minimum
import io.konform.validation.constraints.multipleOf
import io.konform.validation.constraints.pattern
import io.konform.validation.constraints.type
import io.konform.validation.constraints.uniqueItems
import io.konform.validation.constraints.uuid
import io.konform.validation.countFieldsWithErrors
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFailsWith

class JSONSchemaStyleConstraintsTest {
class ConstraintsTest {
@Test
fun typeConstraint() {
val anyValidation = Validation<Any> { type<String>() }
Expand All @@ -42,8 +45,8 @@ class JSONSchemaStyleConstraintsTest {
assertEquals(1, countFieldsWithErrors(anyNumberValidation("String")))
assertEquals(1, countFieldsWithErrors(anyNumberValidation(true)))

assertEquals("must be of the correct type", anyValidation(1).get()!![0])
assertEquals("must be of the correct type", anyNumberValidation("String").get()!![0])
assertEquals("must be of type 'String'", anyValidation(1).get()!![0])
assertEquals("must be of type 'Int'", anyNumberValidation("String").get()!![0])
}

@Test
Expand All @@ -61,7 +64,7 @@ class JSONSchemaStyleConstraintsTest {

@Test
fun stringEnumConstraint() {
val validation = Validation<String> { this.enum("OK", "CANCEL") }
val validation = Validation<String> { enum("OK", "CANCEL") }
assertEquals(Valid("OK"), validation("OK"))
assertEquals(Valid("CANCEL"), validation("CANCEL"))
assertEquals(1, countFieldsWithErrors(validation("???")))
Expand Down Expand Up @@ -110,7 +113,7 @@ class JSONSchemaStyleConstraintsTest {
assertEquals(1, countFieldsWithErrors(nullableConstValidation("Konverse")))

assertEquals("must be 'Konform'", validation("Konverse").get()!![0])
assertEquals("must be null", nullableConstNullValidation("Konform").get()!![0])
assertEquals("must be 'null'", nullableConstNullValidation("Konform").get()!![0])
assertEquals("must be 'Konform'", nullableConstValidation(null).get()!![0])
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package io.konform.validation.validationbuilder

import io.konform.validation.PropertyValidationError
import io.konform.validation.Validation
import io.konform.validation.string.notBlank
import io.konform.validation.constraints.notBlank
import io.kotest.assertions.konform.shouldBeInvalid
import io.kotest.assertions.konform.shouldBeValid
import io.kotest.assertions.konform.shouldContainExactlyErrors
Expand Down

0 comments on commit ddf5133

Please sign in to comment.