commonMain.dev.fritz2.validation.validation.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of core-jvm Show documentation
Show all versions of core-jvm Show documentation
Easily build reactive web-apps in Kotlin based on flows and coroutines
package dev.fritz2.validation
import dev.fritz2.core.Inspector
import dev.fritz2.core.inspectorOf
import kotlin.jvm.JvmInline
/**
* Encapsulates the logic for validating a given data-model and some optional metadata.
*
* The validation logic itself is expressed by some function that must be passed as [validate] parameter.
* This function gets the actual model-data [D] and some optional metadata [T] in order to create a [List] of
* validation messages [M]. This value class simply wraps the provided [validate] function in order to make it
* invocable without any ceremony.
*
* It appears to be a good practise, to put the implementation of the passed [validate] function right next to your data
* classes in the `commonMain` section of your Kotlin multiplatform project.
* So you can write the validation logic once and use them on the *JS* and *JVM* side.
*
* @param D data-model to validate
* @param T metadata which perhaps is needed in validation process
*/
@JvmInline
value class Validation(private inline val validate: (D, T?) -> List) {
operator fun invoke(data: D, metadata: T? = null): List = this.validate(data, metadata)
}
/**
* Convenience function for creating a [Validation] instance accepting model- and metadata by working on a
* [MutableList] receiver and using an [Inspector] for getting the right [Inspector.path] from sub-models
* next to the [Inspector.data].
*/
fun validation(validate: MutableList.(Inspector, T?) -> Unit): Validation =
Validation { data, metadata ->
buildList { validate(inspectorOf(data), metadata) }
}
/**
* Convenience function for creating a [Validation] instance only accepting model-data by working on a
* [MutableList] receiver and using an [Inspector] for getting the right [Inspector.path] from sub-models
* next to the [Inspector.data].
*/
fun validation(validate: MutableList.(Inspector) -> Unit): Validation =
Validation { data, _ ->
buildList { validate(inspectorOf(data)) }
}
/**
* Minimal interface for a validation message that exposes the model path for matching relevant sub-model-data and
* probably relevant UI element representation for showing the message and getting information about the valid state
* after validation process.
*/
interface ValidationMessage {
/**
* Path inside your model derived from [Inspector.path]
*/
val path: String
/**
* Decides if the [ValidationMessage] is an error which is needed to determine if validation state is
* successful or not.
*
* It is intentional to explicitly define a message as an error to realize scenarios, where also pure information
* or warning messages could arise, that should *not* stop the process.
*
* If an application considers every message as error, just set this to `true`.
*/
val isError: Boolean
}
/**
* Returns *true* when the list contains no [ValidationMessage] which is marked with [ValidationMessage.isError].
*/
val List.valid: Boolean get() = none { it.isError }
© 2015 - 2024 Weber Informatics LLC | Privacy Policy