README.md

# lab42_message

<!--
DO NOT EDIT THIS FILE
It has been generated from the template `README.md.eex` by Extractly (https://github.com/RobertDober/extractly.git)
and any changes you make in this file will most likely be lost
-->

[![Build Status](https://travis-ci.org/RobertDober/lab42_message.svg?branch=master)](https://travis-ci.org/RobertDober/lab42_message)
[![Coverage Status](https://coveralls.io/repos/github/RobertDober/lab42_message/badge.svg?branch=master)](https://coveralls.io/github/RobertDober/lab42_message?branch=master)
[![Hex.pm](https://img.shields.io/hexpm/v/lab42_message.svg)](https://hex.pm/packages/lab42_message)
[![Hex.pm](https://img.shields.io/hexpm/dw/lab42_message.svg)](https://hex.pm/packages/lab42_message)
[![Hex.pm](https://img.shields.io/hexpm/dt/lab42_message.svg)](https://hex.pm/packages/lab42_message)


## Synopsis

Simple Library to manage Errors and Results.

Its Simplicity is inspired by
 Dave Thomas' keynote, condensed here https://pragdave.me/blog/2018/06/02/project-structure.html

## API

A container for error messages.

Defining some severities.

Create results depending on error messages.

Convenience functions for adding, filtering and sorting messages.


### Lab42.Message.add_critical/3

Create a message with severity :critical and add in front of other messages

    iex(10)> add_critical([], "Just a critical message", {1, 3})
    [%Lab42.Message{message: "Just a critical message", severity: :critical, location: {1, 3}}]
### Lab42.Message.add_debug/3

Create a message with severity :debug and add in front of other messages

    iex(2)> add_debug([], "Just a debug message", {1, 3})
    [%Lab42.Message{message: "Just a debug message", severity: :debug, location: {1, 3}}]
### Lab42.Message.add_error/3

Create a message with severity :error and add in front of other messages

    iex(8)> add_error([], "Just a error message", {1, 3})
    [%Lab42.Message{message: "Just a error message", severity: :error, location: {1, 3}}]
### Lab42.Message.add_fatal/3

Create a message with severity :fatal and add in front of other messages

    iex(12)> add_fatal([], "Just a fatal message", {1, 3})
    [%Lab42.Message{message: "Just a fatal message", severity: :fatal, location: {1, 3}}]
### Lab42.Message.add_info/3

Create a message with severity :info and add in front of other messages

    iex(4)> add_info([], "Just a info message", {1, 3})
    [%Lab42.Message{message: "Just a info message", severity: :info, location: {1, 3}}]
### Lab42.Message.add_warning/3

Create a message with severity :warning and add in front of other messages

    iex(6)> add_warning([], "Just a warning message", {1, 3})
    [%Lab42.Message{message: "Just a warning message", severity: :warning, location: {1, 3}}]
### Lab42.Message.make_critical/2

Create a message with severity :critical

    iex(11)> make_critical("Just a critical message", {1, 3})
    %Lab42.Message{message: "Just a critical message", severity: :critical, location: {1, 3}}
### Lab42.Message.make_debug/2

Create a message with severity :debug

    iex(3)> make_debug("Just a debug message", {1, 3})
    %Lab42.Message{message: "Just a debug message", severity: :debug, location: {1, 3}}
### Lab42.Message.make_error/2

Create a message with severity :error

    iex(9)> make_error("Just a error message", {1, 3})
    %Lab42.Message{message: "Just a error message", severity: :error, location: {1, 3}}
### Lab42.Message.make_fatal/2

Create a message with severity :fatal

    iex(13)> make_fatal("Just a fatal message", {1, 3})
    %Lab42.Message{message: "Just a fatal message", severity: :fatal, location: {1, 3}}
### Lab42.Message.make_info/2

Create a message with severity :info

    iex(5)> make_info("Just a info message", {1, 3})
    %Lab42.Message{message: "Just a info message", severity: :info, location: {1, 3}}
### Lab42.Message.make_warning/2

Create a message with severity :warning

    iex(7)> make_warning("Just a warning message", {1, 3})
    %Lab42.Message{message: "Just a warning message", severity: :warning, location: {1, 3}}



### Lab42.Message.max_severity/2

Returns the maximum priority of messages
A list of messages can be passed in 

    iex(15)> messages =
    ...(15)>   []
    ...(15)>   |> add_error("error1", 1)
    ...(15)>   |> add_info("info2", 2)
    ...(15)>   |> add_warning("warning3", 3)
    ...(15)> max_severity(messages)
    :error

However a list of message tuples is also allowed

    iex(16)> messages =
    ...(16)>   []
    ...(16)>   |> add_error("error1", 1)
    ...(16)>   |> add_fatal("fatal2", 2)
    ...(16)>   |> add_warning("warning3", 3)
    ...(16)>   |> messages()
    ...(16)> max_severity(messages)
    :fatal

In accordance of the robustness principle the last can even be mixed

    iex(17)> messages =
    ...(17)>   []
    ...(17)>   |> add_error("what an error", 42)
    ...(17)>   |> add_info("what an info", 42)
    ...(17)> max_severity([{:critical, "", nil}|messages])
    :critical

And last, but not least it might be convenient to get the severity_value instead of
the symbolic severity

    iex(18)> messages =
    ...(18)>   []
    ...(18)>   |> add_error("what an error", 42)
    ...(18)>   |> add_info("what an info", 42)
    ...(18)> max_severity([{:critical, "", nil}|messages], value: true)
    4


### Lab42.Message.messages/2

Extract messages from a list of messages into a library agnositic form as triples.
As all the `add_*` functions create a list in reverse order, this function also
rereverses the message tuples.

    iex(19)> messages =
    ...(19)>   []
    ...(19)>   |> add_error("error1", 1)
    ...(19)>   |> add_info("info2", 2)
    ...(19)>   |> add_warning("warning3", 3)
    ...(19)> messages(messages)
    [ {:error, "error1", 1}, {:warning, "warning3", 3} ]

As you can see only messages with severity of warning and up are returned.

One can of course get messages with less severity too:

    iex(20)> messages =
    ...(20)>   []
    ...(20)>   |> add_error("error1", 1)
    ...(20)>   |> add_info("info2", 2)
    ...(20)>   |> add_debug("debug3", 3)
    ...(20)> messages(messages, severity: :info)
    [ {:error, "error1", 1}, {:info, "info2", 2} ]

And, eventually, for your convenience, instead of `severity: :debug` a shorter and more expressive `:all` can be passed in

    iex(21)> messages =
    ...(21)>   []
    ...(21)>   |> add_error("error1", 1)
    ...(21)>   |> add_info("info2", 2)
    ...(21)>   |> add_debug("debug3", 3)
    ...(21)> messages(messages, :all)
    [ {:error, "error1", 1}, {:info, "info2", 2}, {:debug, "debug3", 3} ]

### Lab42.Message.result/3

Wrap a value and error messages into a result tuple, messages themselves
are converted to message tuples as with `messages`. Also warnings still
deliver an `:ok` reesult.œ

    iex(22)> messages = []
    ...(22)>   |> add_debug("hello", 1)
    ...(22)>   |> add_info("hello again", 2)
    ...(22)>   |> add_warning("world", 3)
    ...(22)> result(messages, "result")
    {:ok, "result", [{:warning, "world", 3}]}

However the presence of errors or worse returns an `:error` result.
N.B. that the input can be a mixture of `Lab42.Message` structs and
agnostic tuples.

    iex(23)> messages = [{:fatal, "that was not good", 0}]
    ...(23)>   |> add_debug("hello", 1)
    ...(23)> result(messages, "result")
    {:error, "result", [{:fatal, "that was not good", 0}]}

As with `messages` one can control what level of errors shall be included, here
is an example where warnings are surpressed

    iex(24)> messages = []
    ...(24)>   |> add_error("hello", 1)
    ...(24)>   |> add_info("hello again", 2)
    ...(24)>   |> add_warning("world", 3)
    ...(24)> result(messages, 42, severity: :error)
    {:error, 42, [{:error, "hello", 1}]}





## Author

Copyright © 2019 Robert Dober, mailto:robert.dober@gmail.com

## License

[Apache-2.0](LICENSE)
<!-- SPDX-License-Identifier: Apache-2.0 -->