lib/wolf_core/utils/result.rb



class Result
  attr_accessor :data, :error

  def initialize(success:, data: nil, error: nil)
    @success = success
    @data = data
    @error = error
  end

  def self.success(data: {})
    Result.new(success: true, data: OpenStruct.new(data))
  end

  def self.failure(error: {})
    Result.new(success: false, error: OpenStruct.new(error))
  end

  def self.try
    try_result = yield
    unless try_result.is_a?(Result)
      raise StandardError, "Try result must be a Result object, got: #{try_result.class}"
    end
    try_result
  rescue StandardError => e
    Result.failure(error: { message: e.message, error_class: e.class, backtrace: e.backtrace })
  end

  def success?
    @success
  end

  def failure?
    !@success
  end

  def to_h
    {
      success: @success,
      data: @data,
      error: @error,
    }
  end

  def slice(*keys)
    if success?
      sliced_data = @data.to_h.slice(*keys)
      Result.success(data: sliced_data)
    else
      sliced_error = @error.to_h.slice(*keys)
      Result.failure(error: sliced_error)
    end
  end

  def fold(success: nil, failure: nil)
    fold_result = if success?
      if success.respond_to?(:call)
        success.call(@data)
      else
        if block_given?
          yield(@data)
        else
          self
        end
      end
    else
      if failure.respond_to?(:call)
        failure.call(@error)
      else
        self
      end
    end

    unless fold_result.is_a?(Result)
      raise StandardError, "Fold result must be a Result object, got: #{fold_result.class}"
    end
    fold_result
  end

  def raise_error
    if failure?
      err_class = error.error_class || StandardError
      e = err_class.new(error.message)
      if error.backtrace
        e.set_backtrace(error.backtrace)
      end
      raise e
    end
  end
end