### Kotlin Result Example with Custom Errors and No Wrappers Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md Demonstrates how to use the ItsOk library in Kotlin to define custom error types using sealed interfaces and `ItsError`. It shows how to return results without explicitly wrapping them in `Ok` or `Error` objects, and how to chain operations using `map` and handle potential failures with `getOrElse`. ```kotlin import io.paoloconte.itsok.* sealed interface RepositoryError: ItsError { object NotFound : RepositoryError data class InvalidInput(val message: String) : RepositoryError } data class User(val name: String, val age: Int): ItsOk fun findUser(id: Int): Result { return if (id == 1) User("Mario", 30) // no need to wrap in Ok else RepositoryError.NotFound // no need to wrap in Error } fun main() { val result = findUser(1) .map { user -> user.name } .getOrElse { println("User not found") return } println("User name is -> $result") } ``` -------------------------------- ### Chain Operations with flatMap and andThen in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Illustrates how to chain multiple operations that return Result types using `flatMap` and `andThen` (an alias for `flatMap`). This allows for sequential execution, short-circuiting on the first encountered error, and transforming the final success value. ```kotlin import io.paoloconte.itsok.* data class User(val id: Int, val name: String): ItsOk data class Order(val id: Int, val userId: Int, val total: Double): ItsOk sealed interface AppError: ItsError { object UserNotFound : AppError object OrderNotFound : AppError object Unauthorized : AppError } fun findUser(id: Int): Result = if (id == 1) User(1, "Alice") else AppError.UserNotFound fun findLatestOrder(userId: Int): Result = if (userId == 1) Order(100, 1, 99.99) else AppError.OrderNotFound fun validateAccess(user: User): Result = if (user.id > 0) user else AppError.Unauthorized // Chain multiple operations - stops at first error val result = findUser(1) .flatMap { user -> validateAccess(user) } .andThen { user -> findLatestOrder(user.id) } .map { order -> "Order #${order.id}: $${order.total}" } println(result.getOrNull()) // Order #100: $99.99 // With error - chain stops early val errorResult = findUser(999) .flatMap { user -> findLatestOrder(user.id) } println(errorResult.getErrorOrNull()) // UserNotFound ``` -------------------------------- ### Add ItsOk Dependency using Gradle Kotlin DSL Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Includes instructions for adding the core ItsOk library and the optional Kotest extensions to your project's build.gradle.kts file. This allows you to leverage ItsOk's error handling and testing capabilities. ```kotlin // build.gradle.kts dependencies { // Core library implementation("io.paoloconte:kotlin-itsok:1.1.5") // Optional: Kotest extensions for testing testImplementation("io.paoloconte:kotlin-itsok-kotest:1.1.5") } ``` -------------------------------- ### Extract Values with Fallbacks using getOrElse and getOrDefault in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Demonstrates how to extract the success value from a Result or provide a fallback value using `getOrDefault` for a static fallback or `getOrElse` for a computed fallback based on the error. This pattern is also useful for early returns in functions. ```kotlin import io.paoloconte.itsok.* data class Config(val timeout: Int, val retries: Int): ItsOk sealed interface ConfigError: ItsError { object FileNotFound : ConfigError data class ParseError(val line: Int) : ConfigError } fun loadConfig(): Result = ConfigError.FileNotFound // Simple default value val config1 = loadConfig().getOrDefault(Config(timeout = 30, retries = 3)) println(config1) // Config(timeout=30, retries=3) // Compute default based on error val config2 = loadConfig().getOrElse { error -> when (error) { ConfigError.FileNotFound -> Config(timeout = 60, retries = 5) is ConfigError.ParseError -> Config(timeout = 30, retries = 1) } } println(config2) // Config(timeout=60, retries=5) // Early return pattern fun processConfig(): String { val config = loadConfig().getOrElse { return "Failed to load config" } return "Timeout: ${config.timeout}" } println(processConfig()) // Failed to load config ``` -------------------------------- ### Implement ItsOk for Unwrapped Success in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Shows how to implement the ItsOk interface, enabling a class to act directly as a Result.Ok without explicit wrapping. The generic type T must match the implementing class. ```kotlin import io.paoloconte.itsok.* // Your domain class implements ItsOk data class User(val id: Int, val name: String, val email: String): ItsOk fun findUser(id: Int): Result { return if (id > 0) User(id, "John Doe", "john@example.com") // No Ok() wrapper needed! else Error("Invalid user ID") } val user = findUser(1) if (user.isOk()) { println("Found: ${user.name}") // Smart cast works - Found: John Doe } ``` -------------------------------- ### Handle Success and Error with fold in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Shows how to use the `fold` function to transform both the success and error cases of a Result into a single, unified result type. This is useful for generating messages, status codes, or any other consolidated output. ```kotlin import io.paoloconte.itsok.* data class User(val name: String): ItsOk sealed interface UserError: ItsError { object NotFound : UserError data class InvalidId(val id: Int) : UserError } fun findUser(id: Int): Result = when { id <= 0 -> UserError.InvalidId(id) id == 1 -> User("Alice") else -> UserError.NotFound } // Fold to a String message val message: String = findUser(1).fold( onSuccess = { user -> "Welcome, ${user.name}!" }, onError = { error -> when (error) { UserError.NotFound -> "User not found" is UserError.InvalidId -> "Invalid ID: ${error.id}" } } ) println(message) // Welcome, Alice! // Fold to HTTP response code val statusCode: Int = findUser(999).fold( onSuccess = { 200 }, onError = { error -> when (error) { UserError.NotFound -> 404 is UserError.InvalidId -> 400 } } ) println(statusCode) // 404 ``` -------------------------------- ### Combine Results with and/or in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt The and and or functions are used to combine multiple Result objects. 'and' requires all Results to be successful (for Unit results), while 'or' returns the first successful Result encountered. ```kotlin import io.paoloconte.itsok.* sealed interface ValidationError: ItsError { data class Invalid(val field: String) : ValidationError } fun validateEmail(email: String): Result = if (email.contains("@")) Ok else Error(ValidationError.Invalid("email")) fun validatePassword(password: String): Result = if (password.length >= 8) Ok else Error(ValidationError.Invalid("password")) // Both validations must pass val bothValid = validateEmail("test@example.com") .and(validatePassword("secret123")) println(bothValid.isOk()) // true val oneFails = validateEmail("invalid") .and(validatePassword("secret123")) println(oneFails.getErrorOrNull()) // Invalid(field=email) // First success wins with `or` fun primaryLookup(id: Int): Result = Error("Primary failed") fun fallbackLookup(id: Int): Result = Ok("Found in fallback") val found = primaryLookup(1).or(fallbackLookup(1)) println(found.getOrNull()) // Found in fallback ``` -------------------------------- ### Result Type Assertions Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md This section details the extension functions available for Result types to assert whether they are 'Ok' or 'Error'. These functions are useful for testing and validation. ```APIDOC ## Result Type Assertions ### Description Provides extension functions to assert the state of a `Result`. ### Methods #### `shouldBeOk()` (Returns T) ##### Description Asserts that the `Result` is an `Ok` value and returns the contained value. ##### Method Extension Function ##### Parameters - **`T`** (reified generic) - The type of the success value. - **`E`** (reified generic) - The type of the error value. ##### Request Example ```kotlin val result: Result = Result.Ok("Success") val value: String = result.shouldBeOk() ``` ##### Response ###### Success Response (T) - **`T`** - The unwrapped success value from the `Result`. ###### Response Example ```kotlin // If result is Result.Ok("Success"), value will be "Success" ``` #### `shouldBeOk()` (Returns Result.Ok) ##### Description Asserts that the `Result` is an `Ok` value and returns the `Result.Ok` instance. ##### Method Extension Function ##### Parameters - **`T`** (reified generic) - The type of the success value. - **`E`** (reified generic) - The type of the error value. ##### Request Example ```kotlin val result: Result = Result.Ok("Success") val okResult: Result.Ok = result.shouldBeOk() ``` ##### Response ###### Success Response (Result.Ok) - **`Result.Ok`** - The `Result.Ok` instance if the original result was `Ok`. ###### Response Example ```kotlin // okResult will be Result.Ok("Success") ``` #### `shouldBeError()` (Returns E) ##### Description Asserts that the `Result` is an `Error` value and returns the contained error. ##### Method Extension Function ##### Parameters - **`T`** (reified generic) - The type of the success value. - **`E`** (reified generic, `ItsError`) - The type of the error value, must be a subtype of `ItsError`. ##### Request Example ```kotlin val result: Result = Result.Error(MyError("Something went wrong")) val error: MyError = result.shouldBeError() ``` ##### Response ###### Success Response (E) - **`E`** - The unwrapped error value from the `Result`. ###### Response Example ```kotlin // If result is Result.Error(MyError("Something went wrong")), error will be MyError("Something went wrong") ``` #### `shouldBeError()` (Returns Result.Error) ##### Description Asserts that the `Result` is an `Error` value and returns the `Result.Error` instance. ##### Method Extension Function ##### Parameters - **`T`** (reified generic) - The type of the success value. - **`E`** (reified generic) - The type of the error value. ##### Request Example ```kotlin val result: Result = Result.Error(123) val errorResult: Result.Error = result.shouldBeError() ``` ##### Response ###### Success Response (Result.Error) - **`Result.Error`** - The `Result.Error` instance if the original result was `Error`. ###### Response Example ```kotlin // errorResult will be Result.Error(123) ``` ``` -------------------------------- ### Assert Result is Ok in Kotlin Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md These extension functions allow you to assert that a Result is in an 'Ok' state and retrieve its value. They are generic and can be used with different Result types. The `reified` keyword enables compile-time type checking. ```kotlin inline fun , reified E> Result.shouldBeOk(): T inline fun Result.shouldBeOk(): Result.Ok ``` -------------------------------- ### Kotlin ItsOk Kotest Extension Dependency Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md Provides the Maven dependency for integrating `kotlin-itsok` with the Kotest testing framework. This dependency enables the use of ItsOk-specific matchers and utilities within Kotest test suites for more convenient testing of Result-based logic. ```kotlin dependencies { implementation("io.paoloconte:kotlin-itsok-kotest:1.1.5") } ``` -------------------------------- ### Test Result States with Kotest Assertions shouldBeOk/shouldBeError Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Provides Kotest matchers for asserting the state of Result objects in tests. These extensions support both standard Kotlin Result types and ItsOk/ItsError patterns, allowing for smart casting of the unwrapped value or error. ```kotlin import io.kotest.core.spec.style.StringSpec import io.paoloconte.itsok.* import io.paoloconte.itsok.kotest.* data class User(val name: String): ItsOk sealed interface UserError: ItsError { object NotFound : UserError } fun findUser(id: Int): Result = if (id == 1) User("Alice") else UserError.NotFound class UserServiceTest : StringSpec({ "should find existing user" { val result = findUser(1) // Assert Ok and get the value with smart cast val user: User = result.shouldBeOk() user.name shouldBe "Alice" } "should return NotFound for missing user" { val result = findUser(999) // Assert Error and get the error with smart cast val error: UserError = result.shouldBeError() error shouldBe UserError.NotFound } "works with wrapped results too" { val wrapped: Result = Ok("hello") val ok: Result.Ok = wrapped.shouldBeOk() ok.wrappedValue shouldBe "hello" val errorResult: Result = Error(404) val err: Result.Error = errorResult.shouldBeError() err.wrappedError shouldBe 404 } }) ``` -------------------------------- ### Implement ItsError for Unwrapped Errors in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Illustrates implementing the ItsError interface, allowing a class to act directly as a Result.Error without wrapping. This is useful for defining error hierarchies with sealed interfaces. ```kotlin import io.paoloconte.itsok.* // Define a sealed hierarchy of errors sealed interface UserError: ItsError { object NotFound : UserError object Unauthorized : UserError data class ValidationError(val field: String, val message: String) : UserError } data class User(val id: Int, val name: String): ItsOk fun getUser(id: Int, hasPermission: Boolean): Result { if (!hasPermission) return UserError.Unauthorized // No Error() wrapper needed! if (id <= 0) return UserError.ValidationError("id", "Must be positive") if (id == 999) return UserError.NotFound return User(id, "Alice") // No Ok() wrapper needed! } val result = getUser(999, true) when { result.isOk() -> println("User: ${result.name}") result.isError() -> when (result) { UserError.NotFound -> println("User not found") UserError.Unauthorized -> println("Access denied") is UserError.ValidationError -> println("Invalid ${result.field}: ${result.message}") } } // Output: User not found ``` -------------------------------- ### Kotlin ItsOk Extension Functions for Result Manipulation Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md Provides a comprehensive list of extension functions available in the ItsOk library for Kotlin's `Result` type. These functions allow for checking the state of a result (`isOk`, `isError`), retrieving values or errors (`getOrNull`, `getErrorOrNull`, `getErrorOrThrow`), transforming results (`map`, `mapError`, `fold`, `flatMap`), and handling errors (`recover`, `onSuccess`, `onError`, `getOrElse`, `getOrDefault`, `flatMapError`, `andThen`, `orElse`). It also includes functions for catching exceptions (`resultCatching`, `suspendCatching`) and combining results (`and`, `or`). ```kotlin fun Result.isOk(): Boolean fun Result.isError(): Boolean fun Result.getOrNull(): T? fun Result.getErrorOrNull(): E? fun Result.getErrorOrThrow(): E fun Result.map(transform: (T) -> R): Result fun Result.mapError(transform: (E) -> R): Result fun Result.recover(transform: (E) -> T): Result fun Result.onSuccess(block: Result.(T) -> Unit): Result fun Result.onError(block: Result.(E) -> Unit): Result fun Result.getOrElse(onFailure: (E) -> T): T fun Result.getOrDefault(defaultValue: T): T fun Result.fold(onSuccess: (T) -> R, onError: (E) -> R): R fun Result.flatMap(transform: Result.(T) -> Result): Result fun Result.flatMapError(transform: Result.(E) -> Result): Result fun Result.andThen(transform: Result.(T) -> Result): Result // same as flatMap fun Result.orElse(onFailure: Result.(E) -> Result): Result // same as flatMapError fun resultCatching(block: () -> T): Result suspend fun suspendCatching(block: suspend () -> T): Result fun Result.getOrThrow(): T fun Result.and(other: Result): Result fun Result.or(other: Result): Result ``` -------------------------------- ### Execute Side Effects with onSuccess/onError in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt The onSuccess and onError functions allow executing side effects like logging or metrics without altering the Result's success or error state. They are useful for observing the outcome of an operation. ```kotlin import io.paoloconte.itsok.* data class User(val id: Int, val name: String): ItsOk sealed interface UserError: ItsError { object NotFound : UserError } fun findUser(id: Int): Result = if (id == 1) User(1, "Alice") else UserError.NotFound // Log success and errors while preserving the chain val result = findUser(1) .onSuccess { user -> println("Found user: ${user.name}") // Found user: Alice } .onError { error -> println("Error occurred: $error") } .map { it.name.uppercase() } println(result.getOrNull()) // ALICE // Combined logging for both cases findUser(999) .onSuccess { println("Success: ${it.name}") } .onError { println("Failed: $it") } // Failed: NotFound ``` -------------------------------- ### Recover Errors to Success with recover in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt The recover function transforms an error state into a success value. This is useful for providing default or fallback values when an operation fails, effectively recovering the computation. ```kotlin import io.paoloconte.itsok.* data class User(val id: Int, val name: String, val isGuest: Boolean = false): ItsOk sealed interface UserError: ItsError { object NotFound : UserError object SessionExpired : UserError } fun findUser(id: Int): Result = if (id == 1) User(1, "Alice") else UserError.NotFound // Recover with a guest user when not found val user = findUser(999) .recover { error -> when (error) { UserError.NotFound -> User(0, "Guest", isGuest = true) UserError.SessionExpired -> User(0, "Guest", isGuest = true) } } println(user.getOrNull()) // User(id=0, name=Guest, isGuest=true) ``` -------------------------------- ### Chain Error Recovery with orElse/flatMapError in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt The orElse and flatMapError functions enable chaining alternative operations when a Result is in an error state. This allows for sequential error handling or fallback strategies. ```kotlin import io.paoloconte.itsok.* data class User(val id: Int, val name: String, val source: String): ItsOk sealed interface CacheError: ItsError { object CacheMiss : CacheError } sealed interface DbError: ItsError { object NotFound : DbError } fun findInCache(id: Int): Result = CacheError.CacheMiss fun findInDatabase(id: Int): Result = if (id == 1) User(1, "Alice", "database") else Error(DbError.NotFound) // Try cache first, fall back to database val user: Result = findInCache(1) .orElse { cacheError -> println("Cache miss, trying database...") // Cache miss, trying database... findInDatabase(1) } println(user.getOrNull()) // User(id=1, name=Alice, source=database) ``` -------------------------------- ### Handle Exceptions with resultCatching/suspendCatching in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt resultCatching and suspendCatching capture exceptions thrown during computation and convert them into a Result type. suspendCatching is specifically designed for use within coroutines. ```kotlin import io.paoloconte.itsok.* // Capture exceptions as Result val result1 = resultCatching { "123".toInt() } println(result1.getOrNull()) // 123 val result2 = resultCatching { "abc".toInt() // Throws NumberFormatException } println(result2.getErrorOrNull()) // java.lang.NumberFormatException: For input string: "abc" // Map throwable to custom error sealed interface ParseError { data class InvalidNumber(val input: String) : ParseError } val parsed: Result = resultCatching { "abc".toInt() } .mapError { ParseError.InvalidNumber("abc") } println(parsed.getErrorOrNull()) // InvalidNumber(input=abc) // Suspend version for coroutines suspend fun fetchData(): String = throw RuntimeException("Network error") suspend fun safeFetch(): Result = suspendCatching { fetchData() } ``` -------------------------------- ### Kotlin ItsOk Library Dependency Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md Specifies the Maven dependency coordinates for including the core `kotlin-itsok` library in a Kotlin project. This allows developers to leverage the enhanced Result handling capabilities provided by the library. ```kotlin dependencies { implementation("io.paoloconte:kotlin-itsok:1.1.5") } ``` -------------------------------- ### Define Result Type in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Demonstrates the basic usage of the Result type, which represents either a success value of type T or an error of type E. It allows any type as an error, unlike Kotlin's standard Result. ```kotlin import io.paoloconte.itsok.* // Basic usage with wrapped values fun divide(a: Int, b: Int): Result { return if (b == 0) Error("Division by zero") else Ok(a / b) } val result = divide(10, 2) when (result) { is Result.Ok -> println("Result: ${result.wrappedValue}") // Result: 5 is Result.Error -> println("Error: ${result.wrappedError}") } ``` -------------------------------- ### Map Success Values in Kotlin Result Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Demonstrates the `map` operation on a Result type, which transforms the success value while preserving any existing error. It returns a new Result with the transformed value or the original error. ```kotlin import io.paoloconte.itsok.* data class User(val id: Int, val name: String, val age: Int): ItsOk data class UserDTO(val displayName: String, val isAdult: Boolean) sealed interface UserError: ItsError { object NotFound : UserError } fun findUser(id: Int): Result = if (id == 1) User(1, "Alice", 25) else UserError.NotFound val dto: Result = findUser(1) .map { user -> UserDTO(user.name.uppercase(), user.age >= 18) } println(dto.getOrNull()) // UserDTO(displayName=ALICE, isAdult=true) // Chained transformations val nameLength: Result = findUser(1) .map { it.name } .map { it.length } println(nameLength.getOrNull()) // 5 ``` -------------------------------- ### Transform Error Values with mapError in Kotlin Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Demonstrates how to use the `mapError` function to transform error values within a Result type while preserving success values. This is useful for converting between different error types, such as from a repository error to a service error. ```kotlin import io.paoloconte.itsok.* sealed interface RepositoryError { object NotFound : RepositoryError data class DatabaseError(val cause: String) : RepositoryError } sealed interface ServiceError { object ResourceNotFound : ServiceError data class InternalError(val message: String) : ServiceError } fun fetchFromDb(id: Int): Result = if (id > 0) Ok("data-$id") else Error(RepositoryError.NotFound) val result: Result = fetchFromDb(-1) .mapError { repoError -> when (repoError) { RepositoryError.NotFound -> ServiceError.ResourceNotFound is RepositoryError.DatabaseError -> ServiceError.InternalError(repoError.cause) } } println(result.getErrorOrNull()) // ResourceNotFound ``` -------------------------------- ### Assert Result is Error in Kotlin Source: https://github.com/paoloconte/kotlin-itsok/blob/main/README.md These extension functions provide a way to assert that a Result is in an 'Error' state and retrieve the error value. They are designed for generic Result types and utilize the `reified` keyword for compile-time safety. ```kotlin inline fun > Result.shouldBeError(): E inline fun Result.shouldBeError(): Result.Error ``` -------------------------------- ### Unwrap or Throw Result Values with getOrThrow/getErrorOrThrow Source: https://context7.com/paoloconte/kotlin-itsok/llms.txt Safely extracts the value from a Result if it's an Ok state, or throws an IllegalStateException if it's an Error. Conversely, getErrorOrThrow extracts the error if it's an Error state, or throws if it's Ok. These are useful when you are certain about the Result's state. ```kotlin import io.paoloconte.itsok.* data class User(val name: String): ItsOk sealed interface UserError: ItsError { object NotFound : UserError } fun findUser(id: Int): Result = if (id == 1) User("Alice") else UserError.NotFound // Get value or throw val user = findUser(1).getOrThrow() println(user.name) // Alice // Throws if error try { findUser(999).getOrThrow() } catch (e: IllegalStateException) { println("Caught: ${e.message}") // Caught: Result is Error } // Get error or throw val error = findUser(999).getErrorOrThrow() println(error) // NotFound ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.