AshCommanded.Commanded.Error (AshCommanded v0.1.0)

View Source

Standardized error handling for AshCommanded.

This module provides a consistent approach to error handling across the AshCommanded extension. It defines error types, formatting, and helper functions for error creation and handling.

Summary

Types

Types of errors that can occur in AshCommanded

t()

Standard error structure for AshCommanded

Functions

Creates an action error.

Creates an aggregate error.

Creates a command error.

Creates a dispatch error.

Returns the errors from a result.

Formats an error for display.

Converts an Ash error to an AshCommanded error.

Converts a Commanded error to an AshCommanded error.

Returns whether a value is an AshCommanded error.

Returns whether a result is an error result.

Creates a new error with the specified type and message.

Converts a single error to a standardized format.

Converts a list of errors to a standardized format.

Creates a projection error.

Creates a transformation error.

Creates a validation error.

Types

error_type()

@type error_type() ::
  :command_error
  | :validation_error
  | :transformation_error
  | :aggregate_error
  | :dispatch_error
  | :action_error
  | :projection_error

Types of errors that can occur in AshCommanded

t()

@type t() :: %AshCommanded.Commanded.Error{
  context: map(),
  field: atom() | nil,
  message: String.t(),
  path: [String.t() | atom()],
  type: error_type(),
  value: any()
}

Standard error structure for AshCommanded

Functions

action_error(message, opts \\ [])

@spec action_error(
  String.t(),
  keyword()
) :: t()

Creates an action error.

Parameters

  • message - The action error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.action_error("Failed to execute action", context: %{action: :create_user})
%AshCommanded.Commanded.Error{
  type: :action_error,
  message: "Failed to execute action",
  path: [],
  field: nil,
  value: nil,
  context: %{action: :create_user}
}

aggregate_error(message, opts \\ [])

@spec aggregate_error(
  String.t(),
  keyword()
) :: t()

Creates an aggregate error.

Parameters

  • message - The aggregate error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.aggregate_error("Aggregate not found", context: %{aggregate_id: "123"})
%AshCommanded.Commanded.Error{
  type: :aggregate_error,
  message: "Aggregate not found",
  path: [],
  field: nil,
  value: nil,
  context: %{aggregate_id: "123"}
}

command_error(message, opts \\ [])

@spec command_error(
  String.t(),
  keyword()
) :: t()

Creates a command error.

Parameters

  • message - The command error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.command_error("Command is missing required field", field: :id)
%AshCommanded.Commanded.Error{
  type: :command_error,
  message: "Command is missing required field",
  path: [],
  field: :id,
  value: nil,
  context: %{}
}

dispatch_error(message, opts \\ [])

@spec dispatch_error(
  String.t(),
  keyword()
) :: t()

Creates a dispatch error.

Parameters

  • message - The dispatch error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.dispatch_error("Failed to dispatch command", context: %{command: "RegisterUser"})
%AshCommanded.Commanded.Error{
  type: :dispatch_error,
  message: "Failed to dispatch command",
  path: [],
  field: nil,
  value: nil,
  context: %{command: "RegisterUser"}
}

errors_from_result(arg1)

@spec errors_from_result(any()) :: [t()]

Returns the errors from a result.

Parameters

  • result - The result to extract errors from

Examples

iex> error = %AshCommanded.Commanded.Error{type: :validation_error, message: "Invalid"}
iex> AshCommanded.Commanded.Error.errors_from_result({:error, error})
[%AshCommanded.Commanded.Error{type: :validation_error, message: "Invalid"}]

iex> AshCommanded.Commanded.Error.errors_from_result({:error, [%AshCommanded.Commanded.Error{type: :validation_error, message: "Invalid"}]})
[%AshCommanded.Commanded.Error{type: :validation_error, message: "Invalid"}]

iex> AshCommanded.Commanded.Error.errors_from_result({:ok, "Success"})
[]

format(error)

@spec format(t()) :: String.t()

Formats an error for display.

Parameters

  • error - The error to format

Examples

iex> error = AshCommanded.Commanded.Error.validation_error("Value must be positive", field: :age, value: -5)
iex> AshCommanded.Commanded.Error.format(error)
"Validation error: Value must be positive (field: age, value: -5)"

from_ash_error(other)

@spec from_ash_error(Ash.Error.t()) :: t() | [t()]

Converts an Ash error to an AshCommanded error.

Parameters

  • ash_error - The Ash error to convert

Examples

iex> AshCommanded.Commanded.Error.from_ash_error(%Ash.Error.Invalid{errors: [%Ash.Error.Changes.InvalidAttribute{field: :name, message: "can't be blank"}]})
%AshCommanded.Commanded.Error{
  type: :validation_error,
  message: "can't be blank",
  path: [],
  field: :name,
  value: nil,
  context: %{source: :ash}
}

from_commanded_error(error)

@spec from_commanded_error(any()) :: t()

Converts a Commanded error to an AshCommanded error.

Parameters

  • commanded_error - The Commanded error to convert

Examples

iex> AshCommanded.Commanded.Error.from_commanded_error(%Commanded.Aggregates.ExecutionError{message: "Failed to execute command"})
%AshCommanded.Commanded.Error{
  type: :aggregate_error,
  message: "Failed to execute command",
  path: [],
  field: nil,
  value: nil,
  context: %{source: :commanded}
}

is_error?(value)

@spec is_error?(any()) :: boolean()

Returns whether a value is an AshCommanded error.

Parameters

  • value - The value to check

Examples

iex> AshCommanded.Commanded.Error.is_error?(%AshCommanded.Commanded.Error{type: :validation_error, message: "Invalid"})
true

iex> AshCommanded.Commanded.Error.is_error?("Not an error")
false

is_error_result?(arg1)

@spec is_error_result?(any()) :: boolean()

Returns whether a result is an error result.

Parameters

  • result - The result to check

Examples

iex> AshCommanded.Commanded.Error.is_error_result?({:error, %AshCommanded.Commanded.Error{}})
true

iex> AshCommanded.Commanded.Error.is_error_result?({:ok, "Success"})
false

new(type, message, opts \\ [])

@spec new(error_type(), String.t(), keyword()) :: t()

Creates a new error with the specified type and message.

Parameters

  • type - The type of error
  • message - The error message
  • opts - Additional options for the error

Options

  • :path - The path to the error in the data structure
  • :field - The specific field that caused the error
  • :value - The value that caused the error
  • :context - Additional context about the error

Examples

iex> AshCommanded.Commanded.Error.new(:validation_error, "Field must be a string")
%AshCommanded.Commanded.Error{
  type: :validation_error,
  message: "Field must be a string",
  path: [],
  field: nil,
  value: nil,
  context: %{}
}

iex> AshCommanded.Commanded.Error.new(:validation_error, "Field must be a string", field: :name, value: 123)
%AshCommanded.Commanded.Error{
  type: :validation_error, 
  message: "Field must be a string",
  path: [],
  field: :name,
  value: 123,
  context: %{}
}

normalize_error(error)

@spec normalize_error(any()) :: [t()]

Converts a single error to a standardized format.

Parameters

  • error - The error to normalize

Examples

iex> AshCommanded.Commanded.Error.normalize_error(%Ash.Error.Changes.InvalidAttribute{field: :name, message: "can't be blank"})
[%AshCommanded.Commanded.Error{type: :validation_error, message: "can't be blank", field: :name, context: %{source: :ash}}]

normalize_errors(errors)

@spec normalize_errors(list()) :: [t()]

Converts a list of errors to a standardized format.

Parameters

  • errors - The list of errors to normalize

Examples

iex> errors = [
...>   %Ash.Error.Changes.InvalidAttribute{field: :name, message: "can't be blank"},
...>   %Commanded.Aggregates.ExecutionError{message: "Failed to execute command"}
...> ]
iex> AshCommanded.Commanded.Error.normalize_errors(errors)
[
  %AshCommanded.Commanded.Error{type: :validation_error, message: "can't be blank", field: :name, context: %{source: :ash}},
  %AshCommanded.Commanded.Error{type: :aggregate_error, message: "Failed to execute command", context: %{source: :commanded}}
]

projection_error(message, opts \\ [])

@spec projection_error(
  String.t(),
  keyword()
) :: t()

Creates a projection error.

Parameters

  • message - The projection error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.projection_error("Failed to apply projection", context: %{event: "UserRegistered"})
%AshCommanded.Commanded.Error{
  type: :projection_error,
  message: "Failed to apply projection",
  path: [],
  field: nil,
  value: nil,
  context: %{event: "UserRegistered"}
}

transformation_error(message, opts \\ [])

@spec transformation_error(
  String.t(),
  keyword()
) :: t()

Creates a transformation error.

Parameters

  • message - The transformation error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.transformation_error("Failed to cast value to integer", field: :age, value: "abc")
%AshCommanded.Commanded.Error{
  type: :transformation_error,
  message: "Failed to cast value to integer",
  path: [],
  field: :age,
  value: "abc",
  context: %{}
}

validation_error(message, opts \\ [])

@spec validation_error(
  String.t(),
  keyword()
) :: t()

Creates a validation error.

Parameters

  • message - The validation error message
  • opts - Additional options for the error

Examples

iex> AshCommanded.Commanded.Error.validation_error("Value must be positive", field: :age, value: -5)
%AshCommanded.Commanded.Error{
  type: :validation_error,
  message: "Value must be positive",
  path: [],
  field: :age,
  value: -5,
  context: %{}
}