Skip to content

Releases: caiolandgraf/result-pattern

🚀 Result Pattern v2.3.2 - Elevating Error Handling with valueOrError, match, and Chaining!

13 Mar 20:33
Compare
Choose a tag to compare

What's New in Result Pattern

This release introduces powerful new features that make working with the Result Pattern even more intuitive:

🎁 valueOrError() - Simplified Access to Values and Errors (Old unwrapOrGetErrors)

// Before: You had to handle Ok and Fail cases separately
if (result.isOk) {
  const value = result.value;
  // Use value
} else {
  const error = result.value;
  // Handle error
}

// Now: Get either the value or the error in one call!
const valueOrError = result.valueOrError();
// If result is Ok, valueOrError contains the success value
// If result is Fail, valueOrError contains the error value

This method is especially powerful when working with error handling:

const userId = getUserId(); // May be invalid
const result = getUser(userId);

// Get either the user or the error message directly
console.log(`Result: ${result.valueOrError()}`);
// If successful: "Result: {id: 123, name: 'Caio'}"
// If failed: "Result: Invalid user ID"

🎮 Elegant Pattern Matching with match

Another powerful feature is the match method, allowing elegant handling of both success and failure cases:

// Traditional approach with if/else
let message;
if (result.isOk) {
  message = `Welcome, ${result.value.name}!`;
} else {
  message = `Error: ${result.value}`;
}

// Now with pattern matching
const message = result.match({
  ok: user => `Welcome, ${user.name}!`,
  fail: error => `Error: ${error}`
});

🔄 Enhanced Flow Control with andThen and orElse

The andThen and orElse methods provide elegant ways to chain operations based on result status:

// andThen executes only if the result is Ok
const result = validateUser(user)
  .andThen(() => saveUser(user))  // Only runs if validation passes
  .andThen(() => sendWelcomeEmail(user));  // Only runs if save succeeds

// orElse provides fallback behavior when a result is Fail
const userData = primaryDataSource.getUser(id)
  .orElse(() => backupDataSource.getUser(id))  // Try backup if primary fails
  .orElse(() => createDefaultUser(id));  // Create default as last resort

🔍 Why These Methods Matter

These methods solve common pain points when working with the Result Pattern:

  • valueOrError: Simplified access to either success values or error values
  • match: Declarative, pattern-based handling of both success and failure cases
  • andThen: Cleaner composition of operations that depend on previous success
  • orElse: Elegant fallback strategies without complex conditional logic

📋 Complete Feature List

This release builds on our solid foundation:

  • Type-safe error handling with Ok<V, E> and Fail<V, E> classes
  • Powerful transformation methods like map, flatMap, and mapFails
  • Error aggregation with ResultUtils.combine
  • Flexible value extraction with unwrap, unwrapOr, and unwrapOrElse
  • Value/error swapping with flip
  • Direct value/error access with valueOrError
  • Elegant pattern matching with match
  • Enhanced flow control with and, andThen, or, and orElse

🛠️ Migration Guide

This is a minor release with full backward compatibility. Simply update your package:

# npm
npm update @eicode/result-pattern

# yarn
yarn upgrade @eicode/result-pattern

# pnpm
pnpm update @eicode/result-pattern

📚 Usage Examples

Comprehensive Error Handling with Pattern Matching

function processPayment(paymentDetails) {
  return validatePaymentDetails(paymentDetails)
    .flatMap(details => processTransaction(details))
    .match({
      ok: receipt => ({
        success: true,
        receipt,
        message: "Payment processed successfully!"
      }),
      fail: errors => ({
        success: false,
        errors,
        message: "Payment processing failed"
      })
    });
}

Complex Operations with andThen and orElse

function getUserData(userId: string): Result<UserData, string> {
  return authenticateRequest()
    .andThen(() => checkUserPermissions(userId))
    .andThen(() => fetchUserFromPrimaryDB(userId))
    .orElse(() => fetchUserFromBackupDB(userId))
    .map(user => enrichUserData(user));
}

// Handle the result with valueOrError
const result = await getUserData("user-123");
const userOrError = result.valueOrError();

if (result.isOk) {
  renderUserProfile(userOrError);
} else {
  displayError(`Failed to load user: ${userOrError}`);
}

Form Validation with Combined Results

function validateForm(formData) {
  const name = validateName(formData.name);
  const email = validateEmail(formData.email);
  const password = validatePassword(formData.password);
  
  // Combine all validations to get all errors at once
  return ResultUtils.combine(name, email, password)
    .match({
      ok: ([validName, validEmail, validPassword]) => {
        return {
          success: true,
          data: { name: validName, email: validEmail, password: validPassword }
        };
      },
      fail: errors => {
        return {
          success: false,
          errors
        };
      }
    });
}

Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf and @JuniorBecari10

🚀 Result Pattern v2.2.0 - Introducing unwrapOrGetErrors()

13 Mar 19:11
Compare
Choose a tag to compare

What's New

This release introduces a powerful new method that makes working with errors even more convenient:

🎁 unwrapOrGetErrors() - The Best of Both Worlds

// Before: You had to handle Ok and Fail cases separately
if (result.isOk) {
  const value = result.value;
  // Use value
} else {
  const error = result.value;
  // Handle error
}

// Now: Get either the value or the error in one call!
const valueOrError = result.unwrapOrGetErrors();
// If result is Ok, valueOrError contains the success value
// If result is Fail, valueOrError contains the error value

This method is especially powerful when working with combined results:

const email = Email.try("[email protected]");
const password = StrongPassword.try("weak123");

const combined = ResultUtils.combine(email, password);

// Get either the valid data or all validation errors at once
console.log(combined.unwrapOrGetErrors());
// If validation fails: ["Password too weak"]
// If validation passes: [Email, StrongPassword]

🔍 Why This Matters

The new unwrapOrGetErrors() method solves a common pain point when working with the Result Pattern:

  • No more type constraints when you just want to access error values
  • Cleaner code with fewer conditional branches
  • Simplified error handling in combined results
  • Better developer experience with less boilerplate

📋 Complete Feature List

This release builds on our solid foundation:

  • Type-safe error handling with Ok<V, E> and Fail<V, E> classes
  • Powerful transformation methods like map, flatMap, and mapFails
  • Error aggregation with ResultUtils.combine
  • Flexible value extraction with unwrap, unwrapOr, and unwrapOrElse
  • Logical operations with and and or methods
  • Value/error swapping with flip
  • NEW: Direct error access with unwrapOrGetErrors

🛠️ Migration Guide

This is a minor release with full backward compatibility. Simply update your package:

# npm
npm update @eicode/result-pattern

# yarn
yarn upgrade @eicode/result-pattern

# pnpm
pnpm update @eicode/result-pattern

Then start using the new unwrapOrGetErrors() method wherever you need to access either success values or error values without type constraints.

📚 Usage Examples

Form Validation

function validateForm(formData: FormData) {
  const name = validateName(formData.get('name'));
  const email = validateEmail(formData.get('email'));
  const password = validatePassword(formData.get('password'));
  
  const result = ResultUtils.combine(name, email, password);
  
  // Get either the validated data or all validation errors
  const dataOrErrors = result.unwrapOrGetErrors();
  
  if (result.isFail) {
    // dataOrErrors is an array of error messages
    displayErrors(dataOrErrors);
  } else {
    // dataOrErrors is a tuple of validated values
    submitForm(dataOrErrors);
  }
}

API Request Handling

async function fetchUserData(userId: string) {
  try {
    const response = await fetch(`/api/users/${userId}`);
    
    if (!response.ok) {
      return new Fail(`HTTP error: ${response.status}`);
    }
    
    const data = await response.json();
    return new Ok(data);
  } catch (error) {
    return new Fail(`Network error: ${error.message}`);
  }
}

// In your component:
const userData = await fetchUserData(userId);
const userOrError = userData.unwrapOrGetErrors();

if (userData.isOk) {
  renderUserProfile(userOrError);
} else {
  showErrorMessage(userOrError);
}

Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf

Robust Error Handling & Smarter Result Composition ⚡

13 Mar 17:24
Compare
Choose a tag to compare

🚀 New Additions:

✅ 📌 Introduced Ok and Fail result classes for more structured error handling.
✅ 🛠️ Added a generic IResult interface with methods to handle both success and failure results.
✅ 🌀 Enhanced methods like map, flatMap, mapFails, flip for better chaining and error propagation.
✅ ⚡ New utilities like unwrapOrElse and unwrapOr for handling fallbacks.
✅ 🔄 Expanded the combine utility for combining multiple results with error propagation.

Differences between versions
  • Types:

    • v2.0.0: The Result type defines the generic parameters <V, E>, while Ok and Fail classes are more explicit with defaults (V = never, E = never).
    • v2.1.0: The Result type uses default values (V = unknown, E = unknown) for more flexibility.
  • Method Implementations:

    • v2.0.0: Methods like map, flatMap, unwrapOrElse are more streamlined and return the same type (Ok or Fail) for chaining without much type manipulation.
    • v2.1.0: The mapFails method is more precise in how it deals with failures, clearly transforming errors and allowing for stronger type safety.
  • Combine Utility:

    • v2.0.0: The combine function ensures that errors are aggregated by collecting them from all Fail results and returns a single Fail containing all error values.
    • v2.1.0: The combine function is slightly modified to ensure it handles empty Fail values more effectively and uses the unwrapOr method to extract values in the Ok case.
  • Error Propagation:

    • v2.0.0: Focuses on a simpler structure where the unwrap function throws an error if called on a Fail.
    • v2.1.0: Adds more functionality to handle fallback values (unwrapOr, unwrapOrElse), improving error recovery flexibility.

Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf


Enhanced Error Handling & Safe Data Flow 🚀

13 Mar 15:06
Compare
Choose a tag to compare

🚀 New Additions:

✅ 📌 API response handling using Result for safe data retrieval.
✅ 🛠️ Form validation example, combining multiple Result instances.
✅ 🌀 Transformation pipelines demonstrating map, flatMap, and unwrapOrElse.
✅ ⚡ Nested Result handling for more complex cases.
✅ 🔄 Fallback mechanisms using unwrapOrElse.
✅ 🛑 Error propagation and handling via mapFails.


Made with 💻, ☕, and a bit of 🪄 by @caiolandgraf