From 508dd6f728e1a5e2543724219ae201a6807029e7 Mon Sep 17 00:00:00 2001 From: David Hoepelman Date: Mon, 1 Apr 2024 13:24:36 +0200 Subject: [PATCH] Enable explicit API mode --- build.gradle.kts | 3 ++ .../io/konform/validation/Validation.kt | 16 +++++---- .../konform/validation/ValidationBuilder.kt | 35 +++++++++--------- .../io/konform/validation/ValidationResult.kt | 20 +++++------ .../validation/jsonschema/JsonSchema.kt | 36 +++++++++---------- 5 files changed, 59 insertions(+), 51 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 89f810b..001050e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,6 +34,9 @@ group = projectGroup version = projectVersion kotlin { + // Since we are a library, prevent accidentally making things part of the public API + explicitApi() + sourceSets.all { languageSettings { languageVersion = kotlinApiTarget diff --git a/src/commonMain/kotlin/io/konform/validation/Validation.kt b/src/commonMain/kotlin/io/konform/validation/Validation.kt index ddeefdf..c992e79 100644 --- a/src/commonMain/kotlin/io/konform/validation/Validation.kt +++ b/src/commonMain/kotlin/io/konform/validation/Validation.kt @@ -2,17 +2,21 @@ package io.konform.validation import io.konform.validation.internal.ValidationBuilderImpl -interface Validation { - companion object { - operator fun invoke(init: ValidationBuilder.() -> Unit): Validation { +public interface Validation { + public companion object { + public operator fun invoke(init: ValidationBuilder.() -> Unit): Validation { val builder = ValidationBuilderImpl() return builder.apply(init).build() } } - fun validate(value: T): ValidationResult + public fun validate(value: T): ValidationResult - operator fun invoke(value: T) = validate(value) + public operator fun invoke(value: T): ValidationResult = validate(value) } -class Constraint internal constructor(val hint: String, val templateValues: List, val test: (R) -> Boolean) +public class Constraint internal constructor( + public val hint: String, + public val templateValues: List, + public val test: (R) -> Boolean, +) diff --git a/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt b/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt index 666248c..aece51e 100644 --- a/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt +++ b/src/commonMain/kotlin/io/konform/validation/ValidationBuilder.kt @@ -13,18 +13,18 @@ import kotlin.reflect.KProperty1 private annotation class ValidationScope @ValidationScope -abstract class ValidationBuilder { - abstract fun build(): Validation +public abstract class ValidationBuilder { + public abstract fun build(): Validation - abstract fun addConstraint( + public abstract fun addConstraint( errorMessage: String, vararg templateValues: String, test: (T) -> Boolean, ): Constraint - abstract infix fun Constraint.hint(hint: String): Constraint + public abstract infix fun Constraint.hint(hint: String): Constraint - abstract operator fun KProperty1.invoke(init: ValidationBuilder.() -> Unit) + public abstract operator fun KProperty1.invoke(init: ValidationBuilder.() -> Unit) internal abstract fun onEachIterable( prop: KProperty1>, @@ -32,7 +32,7 @@ abstract class ValidationBuilder { ) @JvmName("onEachIterable") - infix fun KProperty1>.onEach(init: ValidationBuilder.() -> Unit) = onEachIterable(this, init) + public infix fun KProperty1>.onEach(init: ValidationBuilder.() -> Unit): Unit = onEachIterable(this, init) internal abstract fun onEachArray( prop: KProperty1>, @@ -40,7 +40,7 @@ abstract class ValidationBuilder { ) @JvmName("onEachArray") - infix fun KProperty1>.onEach(init: ValidationBuilder.() -> Unit) = onEachArray(this, init) + public infix fun KProperty1>.onEach(init: ValidationBuilder.() -> Unit): Unit = onEachArray(this, init) internal abstract fun onEachMap( prop: KProperty1>, @@ -48,31 +48,32 @@ abstract class ValidationBuilder { ) @JvmName("onEachMap") - infix fun KProperty1>.onEach(init: ValidationBuilder>.() -> Unit) = onEachMap(this, init) + public infix fun KProperty1>.onEach(init: ValidationBuilder>.() -> Unit): Unit = + onEachMap(this, init) - abstract infix fun KProperty1.ifPresent(init: ValidationBuilder.() -> Unit) + public abstract infix fun KProperty1.ifPresent(init: ValidationBuilder.() -> Unit) - abstract infix fun KProperty1.required(init: ValidationBuilder.() -> Unit) + public abstract infix fun KProperty1.required(init: ValidationBuilder.() -> Unit) - abstract fun run(validation: Validation) + public abstract fun run(validation: Validation) - abstract val KProperty1.has: ValidationBuilder + public abstract val KProperty1.has: ValidationBuilder } -fun ValidationBuilder.ifPresent(init: ValidationBuilder.() -> Unit) { +public fun ValidationBuilder.ifPresent(init: ValidationBuilder.() -> Unit) { val builder = ValidationBuilderImpl() init(builder) run(OptionalValidation(builder.build())) } -fun ValidationBuilder.required(init: ValidationBuilder.() -> Unit) { +public fun ValidationBuilder.required(init: ValidationBuilder.() -> Unit) { val builder = ValidationBuilderImpl() init(builder) run(RequiredValidation(builder.build())) } @JvmName("onEachIterable") -fun > ValidationBuilder.onEach(init: ValidationBuilder.() -> Unit) { +public fun > ValidationBuilder.onEach(init: ValidationBuilder.() -> Unit) { val builder = ValidationBuilderImpl() init(builder) @Suppress("UNCHECKED_CAST") @@ -80,7 +81,7 @@ fun > ValidationBuilder.onEach(init: ValidationBuilder. } @JvmName("onEachArray") -fun ValidationBuilder>.onEach(init: ValidationBuilder.() -> Unit) { +public fun ValidationBuilder>.onEach(init: ValidationBuilder.() -> Unit) { val builder = ValidationBuilderImpl() init(builder) @Suppress("UNCHECKED_CAST") @@ -88,7 +89,7 @@ fun ValidationBuilder>.onEach(init: ValidationBuilder.() -> Unit } @JvmName("onEachMap") -fun > ValidationBuilder.onEach(init: ValidationBuilder>.() -> Unit) { +public fun > ValidationBuilder.onEach(init: ValidationBuilder>.() -> Unit) { val builder = ValidationBuilderImpl>() init(builder) @Suppress("UNCHECKED_CAST") diff --git a/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt b/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt index 6cddfff..6521a76 100644 --- a/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt +++ b/src/commonMain/kotlin/io/konform/validation/ValidationResult.kt @@ -2,9 +2,9 @@ package io.konform.validation import kotlin.reflect.KProperty1 -interface ValidationError { - val dataPath: String - val message: String +public interface ValidationError { + public val dataPath: String + public val message: String } internal data class PropertyValidationError( @@ -16,7 +16,7 @@ internal data class PropertyValidationError( } } -interface ValidationErrors : List +public interface ValidationErrors : List internal object NoValidationErrors : ValidationErrors, List by emptyList() @@ -26,15 +26,15 @@ internal class DefaultValidationErrors(private val errors: List } } -sealed class ValidationResult { - abstract operator fun get(vararg propertyPath: Any): List? +public sealed class ValidationResult { + public abstract operator fun get(vararg propertyPath: Any): List? - abstract fun map(transform: (T) -> R): ValidationResult + public abstract fun map(transform: (T) -> R): ValidationResult - abstract val errors: ValidationErrors + public abstract val errors: ValidationErrors } -data class Invalid( +public data class Invalid( internal val internalErrors: Map>, ) : ValidationResult() { override fun get(vararg propertyPath: Any): List? = internalErrors[propertyPath.joinToString("", transform = ::toPathSegment)] @@ -62,7 +62,7 @@ data class Invalid( } } -data class Valid(val value: T) : ValidationResult() { +public data class Valid(val value: T) : ValidationResult() { override fun get(vararg propertyPath: Any): List? = null override fun map(transform: (T) -> R): ValidationResult = Valid(transform(this.value)) diff --git a/src/commonMain/kotlin/io/konform/validation/jsonschema/JsonSchema.kt b/src/commonMain/kotlin/io/konform/validation/jsonschema/JsonSchema.kt index cab5539..2bef18d 100644 --- a/src/commonMain/kotlin/io/konform/validation/jsonschema/JsonSchema.kt +++ b/src/commonMain/kotlin/io/konform/validation/jsonschema/JsonSchema.kt @@ -4,18 +4,18 @@ import io.konform.validation.Constraint import io.konform.validation.ValidationBuilder import kotlin.math.roundToInt -inline fun ValidationBuilder<*>.type() = +public inline fun ValidationBuilder<*>.type(): Constraint<*> = addConstraint( "must be of the correct type", ) { it is T } -fun ValidationBuilder.enum(vararg allowed: T) = +public fun ValidationBuilder.enum(vararg allowed: T): Constraint = addConstraint( "must be one of: {0}", allowed.joinToString("', '", "'", "'"), ) { it in allowed } -inline fun > ValidationBuilder.enum(): Constraint { +public inline fun > ValidationBuilder.enum(): Constraint { val enumNames = enumValues().map { it.name } return addConstraint( "must be one of: {0}", @@ -23,13 +23,13 @@ inline fun > ValidationBuilder.enum(): Constraint ValidationBuilder.const(expected: T) = +public fun ValidationBuilder.const(expected: T): Constraint = addConstraint( "must be {0}", expected?.let { "'$it'" } ?: "null", ) { expected == it } -fun ValidationBuilder.multipleOf(factor: Number): Constraint { +public fun ValidationBuilder.multipleOf(factor: Number): Constraint { val factorAsDouble = factor.toDouble() require(factorAsDouble > 0) { "multipleOf requires the factor to be strictly larger than 0" } return addConstraint("must be a multiple of '{0}'", factor.toString()) { @@ -38,31 +38,31 @@ fun ValidationBuilder.multipleOf(factor: Number): Constraint } } -fun ValidationBuilder.maximum(maximumInclusive: Number) = +public fun ValidationBuilder.maximum(maximumInclusive: Number): Constraint = addConstraint( "must be at most '{0}'", maximumInclusive.toString(), ) { it.toDouble() <= maximumInclusive.toDouble() } -fun ValidationBuilder.exclusiveMaximum(maximumExclusive: Number) = +public fun ValidationBuilder.exclusiveMaximum(maximumExclusive: Number): Constraint = addConstraint( "must be less than '{0}'", maximumExclusive.toString(), ) { it.toDouble() < maximumExclusive.toDouble() } -fun ValidationBuilder.minimum(minimumInclusive: Number) = +public fun ValidationBuilder.minimum(minimumInclusive: Number): Constraint = addConstraint( "must be at least '{0}'", minimumInclusive.toString(), ) { it.toDouble() >= minimumInclusive.toDouble() } -fun ValidationBuilder.exclusiveMinimum(minimumExclusive: Number) = +public fun ValidationBuilder.exclusiveMinimum(minimumExclusive: Number): Constraint = addConstraint( "must be greater than '{0}'", minimumExclusive.toString(), ) { it.toDouble() > minimumExclusive.toDouble() } -fun ValidationBuilder.minLength(length: Int): Constraint { +public fun ValidationBuilder.minLength(length: Int): Constraint { require(length >= 0) { IllegalArgumentException("minLength requires the length to be >= 0") } return addConstraint( "must have at least {0} characters", @@ -70,7 +70,7 @@ fun ValidationBuilder.minLength(length: Int): Constraint { ) { it.length >= length } } -fun ValidationBuilder.maxLength(length: Int): Constraint { +public fun ValidationBuilder.maxLength(length: Int): Constraint { require(length >= 0) { IllegalArgumentException("maxLength requires the length to be >= 0") } return addConstraint( "must have at most {0} characters", @@ -78,15 +78,15 @@ fun ValidationBuilder.maxLength(length: Int): Constraint { ) { it.length <= length } } -fun ValidationBuilder.pattern(pattern: String) = pattern(pattern.toRegex()) +public fun ValidationBuilder.pattern(pattern: String): Constraint = pattern(pattern.toRegex()) -fun ValidationBuilder.pattern(pattern: Regex) = +public fun ValidationBuilder.pattern(pattern: Regex): Constraint = addConstraint( "must match the expected pattern", pattern.toString(), ) { it.matches(pattern) } -inline fun ValidationBuilder.minItems(minSize: Int): Constraint = +public inline fun ValidationBuilder.minItems(minSize: Int): Constraint = addConstraint( "must have at least {0} items", minSize.toString(), @@ -99,7 +99,7 @@ inline fun ValidationBuilder.minItems(minSize: Int): Constraint ValidationBuilder.maxItems(maxSize: Int): Constraint = +public inline fun ValidationBuilder.maxItems(maxSize: Int): Constraint = addConstraint( "must have at most {0} items", maxSize.toString(), @@ -112,13 +112,13 @@ inline fun ValidationBuilder.maxItems(maxSize: Int): Constraint> ValidationBuilder.minProperties(minSize: Int): Constraint = +public inline fun > ValidationBuilder.minProperties(minSize: Int): Constraint = minItems(minSize) hint "must have at least {0} properties" -inline fun > ValidationBuilder.maxProperties(maxSize: Int): Constraint = +public inline fun > ValidationBuilder.maxProperties(maxSize: Int): Constraint = maxItems(maxSize) hint "must have at most {0} properties" -inline fun ValidationBuilder.uniqueItems(unique: Boolean): Constraint = +public inline fun ValidationBuilder.uniqueItems(unique: Boolean): Constraint = addConstraint( "all items must be unique", ) {