commonMain.schemas.util.SchemaRestrictions.kt Maven / Gradle / Ivy
@file:JvmName("SchemaRestrictions")
package io.kform.schemas.util
import io.kform.Validation
import io.kform.datatypes.File
import io.kform.validations.*
import kotlin.jvm.JvmName
/** Builds the common restrictions of a schema, given its validations. */
public fun commonRestrictions(validations: Iterable>): Map =
buildMap {
if (validations.any { it is Required }) {
put("required", true)
}
val allowedValuesSets =
validations.filterIsInstance>().map { it.allowedValues } +
validations.filterIsInstance>().map { setOf(it.requiredValue) }
if (allowedValuesSets.isNotEmpty()) {
put(
"allowedValues",
allowedValuesSets
.reduce { intersectedAllowedValues, allowedValues ->
intersectedAllowedValues intersect allowedValues
}
.toTypedArray()
)
}
val disallowedValues =
validations.filterIsInstance>().flatMapTo(mutableSetOf()) {
it.disallowedValues
} + validations.filterIsInstance>().map { it.forbiddenValue }
if (disallowedValues.isNotEmpty()) {
put("disallowedValues", disallowedValues.toTypedArray())
}
}
/** Builds the comparable bounds restrictions of a schema, given its validations. */
public fun > comparableBoundsRestrictions(
validations: Iterable>,
typeMin: T? = null,
typeMax: T? = null
): Map = buildMap {
val validationMin = validations.filterIsInstance>().maxOfOrNull { it.min }
val min =
if (typeMin != null && validationMin != null) maxOf(typeMin, validationMin)
else typeMin ?: validationMin
if (min != null) {
put("min", min)
}
val validationMax = validations.filterIsInstance>().minOfOrNull { it.max }
val max =
if (typeMax != null && validationMax != null) minOf(typeMax, validationMax)
else typeMax ?: validationMax
if (max != null) {
put("max", max)
}
val exclusiveMin =
validations.filterIsInstance>().maxOfOrNull { it.exclusiveMin }
if (exclusiveMin != null) {
put("exclusiveMin", exclusiveMin)
}
val exclusiveMax =
validations.filterIsInstance>().minOfOrNull { it.exclusiveMax }
if (exclusiveMax != null) {
put("exclusiveMax", exclusiveMax)
}
}
/** Builds the size bounds restrictions of a schema, given its validations. */
public fun sizeBoundsRestrictions(validations: Iterable>): Map =
buildMap {
val minSize =
(validations.filterIsInstance() + validations.filterIsInstance())
.maxOfOrNull { if (it is MinSize) it.minSize else (it as Size).requiredSize }
if (minSize != null) {
put("minSize", minSize)
}
val maxSize =
(validations.filterIsInstance() + validations.filterIsInstance())
.minOfOrNull { if (it is MaxSize) it.maxSize else (it as Size).requiredSize }
if (maxSize != null) {
put("maxSize", maxSize)
}
}
/** Builds the size length restrictions of a schema, given its validations. */
public fun lengthBoundsRestrictions(
validations: Iterable>
): Map = buildMap {
val minLength =
(validations.filterIsInstance() + validations.filterIsInstance())
.maxOfOrNull { if (it is MinLength) it.minLength else (it as Length).requiredLength }
if (minLength != null) {
put("minLength", minLength)
}
val maxLength =
(validations.filterIsInstance() + validations.filterIsInstance())
.minOfOrNull { if (it is MaxLength) it.maxLength else (it as Length).requiredLength }
if (maxLength != null) {
put("maxLength", maxLength)
}
}
/** Builds the pattern restrictions of a schema, given its validations. */
public fun patternRestrictions(validations: Iterable>): Map =
buildMap {
val matchesValidations = validations.filterIsInstance()
if (matchesValidations.isNotEmpty()) {
put(
"pattern",
if (matchesValidations.size == 1) matchesValidations.first().regex.pattern
else matchesValidations.joinToString("|") { "(${it.regex.pattern})" }
)
}
}
/** Builds the accepted file types restrictions of a schema, given its validations. */
public fun acceptedFileTypesRestrictions(
validations: Iterable>
): Map = buildMap {
val acceptedFileTypesValidations = validations.filterIsInstance()
if (acceptedFileTypesValidations.isNotEmpty()) {
// FIXME: This is incorrect, if one [Accepts] validation allows image/* and another
// image/jpeg, the intersection should be image/jpeg, rather than the empty set
put(
"acceptedFileTypes",
acceptedFileTypesValidations
.map { it.acceptedFileTypes }
.reduce { intersectedAcceptedFileTypes, acceptedFileTypes ->
intersectedAcceptedFileTypes intersect acceptedFileTypes
}
.toTypedArray()
)
}
}