Git Product home page Git Product logo

reactor-validations's Introduction

reactor-validations

A Kotlin based validations api with Project Reactor extensions

Why

Think the Assert utility from Spring Framework or Axon Framework, just with not using IllegalArgumentException (Which in my opinion should be used for technical validation!!!), but with using a dedicated ValidationException. Or maybe you would like to be able to use your own custom exception...

Well now you can :D

Examples:

Synchronous validation:

import nl.juraji.reactor.validations.validate

fun main(args: Array<String>) {
    
    validate {
        useException(MyCustomException::class) // Will use internal `ValidationException` when omitted.
        
        isTrue(someCheck()) { "Check should result in true" }
    }
    
}

Or asynchronous validation with Project Reactor:

import nl.juraji.reactor.validations.validateAsync

validateAsync {
    // Accepts a Mono<Boolean>
    isTrue(Mono.just(true)) { "Check should result in true" }
    
    synchronous {
        // Maybe do some synchronous checks in here as well
        isFalse(args.isEmpty()) { "No args supplied" }
    }
}
    .flatMap(this::continueWithOtherMono)
    // ...

Or use directly in a Project Reactor stream:

import nl.juraji.reactor.validations.validateAsync

// Synchronous
myReactiveService.stuffToValidate()
    .validate {
        isTrue(Mono.just(true)) { "Check should result in true" }
    }
    .map { ... }
    .filter { ... }
    // ...

// Or asynchronous
myReactiveService.stuffToValidate()
    .validateAsync {
        unless(it == null) { // Only when predicate is true, also supports a Mono<Boolean> as predicate
            isTrue(Mono.just(true)) { "Check should result in true" }   
        }
    }
    .map { ... }
    .filter { ... }
// ...

Api

DSL Entry Points

/**
 * Initialize a new asynchronous validation block.
 *
 * @param block An [AsyncValidator] block.
 * @return A [Mono] resulting in `true` when validation succeeds
 * or a [Mono] of [ValidationException] when validation fails.
 */
fun validateAsync(block: AsyncValidator.() -> Unit): Mono<Boolean>

/**
 * Initialize a new validation block.
 *
 * @param block A [Validator] block.
 * @throws ValidationException When a validation fails.
 */
fun validate(block: Validator.() -> Unit): Validator

Synchronous Validator DSL interface

import nl.juraji.reactor.validations.validate

validate {
    /**
     * Override the default [ValidationException] with a custom exception creator
     *
     * @param creator A [Function] which returns the exception to throw based on the input message
     */
    fun useException(creator: (String) -> Throwable): Validator

    /**
     * Validate that [assertion] equals to `true`.
     *
     * @param assertion The [Boolean] value to validate.
     * @throws ValidationException When [assertion] equals to `false`.
     */
    fun isTrue(assertion: Boolean, message: () -> String): Validator

    /**
     * Validate that [assertion] equals to `false`.
     *
     * @param assertion The [Boolean] value to validate.
     * @param message A [Function] which results in a descriptive message.
     * @throws ValidationException When [assertion] equals to `true`.
     */
    fun isFalse(assertion: Boolean, message: () -> String): Validator

    /**
     * Validate that [value] is not `null` or [Unit].
     *
     * @param value The value to validate.
     * @param message A [Function] which results in a descriptive message.
     * @throws ValidationException When [value] equals to `null` or [Unit].
     */
    fun isNotNull(value: Any?, message: () -> String): Validator

    /**
     * Validate that [value] is not `null` or blank.
     *
     * @param value The value to validate.
     * @param message A [Function] which results in a descriptive message.
     * @throws ValidationException When [value] equals to `null` or is blank.
     */
    fun isNotBlank(value: String?, message: () -> String): Validator

    /**
     * Validate that [collection] is not empty.
     *
     * @param collection A [Collection].
     * @param message A [Function] which results in a descriptive message.
     * @throws ValidationException When [collection] is empty.
     */
    fun isNotEmpty(collection: Collection<Any>, message: () -> String): Validator

    /**
     * Ignore [validation] block when [predicate] equals to `true`.
     *
     * @param predicate A [Boolean] value whether to run [validation] block or not.
     * @param validation A new [Validator] block.
     */
    fun unless(predicate: Boolean, validation: Validator.() -> Unit): Validator

    /**
     * Fail with [message].
     *
     * @param message A [Function] which results in a descriptive message.
     * @throws ValidationException Always with [message] as exception message
     */
    fun fail(message: () -> String): Nothing
}

Asynchronous Validator DSL interface

import nl.juraji.reactor.validations.validate

validateAsync {
    /**
     * Override the default [ValidationException] with a custom exception creator
     *
     * @param creator A [Function] which returns the exception to continue with based on the input message
     */
    fun useException(creator: (String) -> Throwable): AsyncValidator

    /**
     * Assert that [assertion] results in `true`.
     *
     * @param assertion A [Mono] resulting in a [Boolean].
     * @param message A [Function] which results in the validation exception message.
     */
    fun isTrue(assertion: Mono<Boolean>, message: () -> String): AsyncValidator

    /**
     * Assert that [assertion] results in `false`.
     *
     * @param assertion A [Mono] resulting in a [Boolean].
     * @param message A [Function] which results in the validation exception message.
     */
    fun isFalse(assertion: Mono<Boolean>, message: () -> String): AsyncValidator

    /**
     * Assert given mono completes
     *
     * @param mono The [Mono] to run
     * @param message Optional: A [Function] which results in the validation exception message.
     * When omitted the resulting [ValidationException] will inherit the emitted error message
     */
    fun <T : Any> succeeds(mono: Mono<T>, message: (() -> String)? = null): AsyncValidator

    /**
     * Run [validation] block only when [predicate] is `false`.
     *
     * @param predicate A [Boolean] value whether to run [validation] or not.
     * @param validation A new [AsyncValidator] block.
     */
    fun unless(predicate: Boolean, validation: AsyncValidator.() -> Unit): AsyncValidator

    /**
     * Run [validation] block only when [predicate] results in `false`.
     *
     * @param predicate A [Mono] of type [Boolean] whether to run [validation] or not.
     * @param validation A new [AsyncValidator] block.
     */
    fun unless(predicate: Mono<Boolean>, validation: AsyncValidator.() -> Unit): AsyncValidator

    /**
     * Run a synchronous [Validator] block as part of this validation.
     *
     * @param validation A new [Validator] block
     */
    fun synchronous(validation: Validator.() -> Unit): AsyncValidator
}

Reactor extension functions

/**
 * Run synchronous validation on the entry value
 *
 * @param block A [Validator] block.
 * @return The entry [Mono] or a [Mono] of [ValidationException] when validation fails.
 */
fun <T : Any> Mono<T>.validate(block: Validator.(T) -> Unit): Mono<T>

/**
 * Run asynchronous validation on the entry value
 *
 * @param block An [AsyncValidator] block.
 * @return The entry [Mono] or a [Mono] of [ValidationException] when validation fails.
 */
fun <T : Any> Mono<T>.validateAsync(block: AsyncValidator.(T) -> Unit): Mono<T>

/**
 * Run synchronous validation on the stream
 *
 * @param block A [Validator] block.
 * @return The entry [Flux] or a [Flux] of [ValidationException] when validation fails.
 */
fun <T : Any> Flux<T>.validate(block: Validator.(T) -> Unit): Flux<T>

/**
 * Run asynchronous validation on the stream
 *
 * @param block An [AsyncValidator] block.
 * @return The entry [Flux] or a [Flux] of [ValidationException] when validation fails.
 */
fun <T : Any> Flux<T>.validateAsync(block: AsyncValidator.(T) -> Unit): Flux<T>

reactor-validations's People

Contributors

juraji avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.