PaackEng/paack-remotedata/1.0.0

NOTE: the latest version is 1.1.0

Remote.Recyclable

This module extends Data preserving the information when reloading the same source.

It helps in scenarios with like this:

  1. Data was never requested

    • Start it with Recyclable.NeverAsked
  2. Request was sent

    • Pipe it into:

      |> Recyclable.toLoading
    • At this point, it will be:

      Recyclable.Loading
  3. Request's Response was received (a Failure error)

    • Pipe it into:

      |> Recyclable.mergeResponse response
    • At this point, it will be:

      Recyclable.Failure error
  4. User press "Retry" button, a new request was sent

    • Pipe it into:

      |> Recyclable.toLoading
    • At this point, it will be:

      Recyclable.Loading
  5. Request's Response was received (a Success data)

    • Pipe it into:

      |> Recyclable.mergeResponse response
    • At this point, it will be:

      Recyclable.Ready data
  6. User press "Refresh" button, a new request was sent

    • Pipe it into:

      |> Recyclable.toLoading
    • At this point, it will be:

      Recyclable.Recycling data Recyclable.Loading
  7. Request's Response was received (a Failure error)

    • Pipe it into:

      |> Recyclable.mergeResponse response
    • At this point, it will be:

      Recyclable.Ready (Recyclable.Recycling data (Recyclable.Failure error))
  8. User press "Refresh" button, a new request was sent

    • Pipe it into:

      |> Recyclable.toLoading
    • At this point, it will be:

      Recyclable.Recycling data Recyclable.Loading
  9. Request's Response was received (a Success data)

    • Pipe it into:

      |> Recyclable.mergeResponse response
    • At this point, it will be:

      Recyclable.Ready data

Types

type Recyclable transportError customError object
= NeverAsked
| Loading
| Failure (RemoteError transportError customError)
| Ready object
| Recycling object (RecyclingStage transportError customError)

A representation for fetchable data with eight states:

First routine states:

  • NotAsked
    • We haven't asked for the data yet.
  • Loading
    • We've asked, but haven't got an answer yet.
  • Failure (Custom error)
    • We asked, but we received one of the custom-defined errors instead. Here's the error.
  • Failure (Transport error)
    • We asked, but something went wrong on the network-side. Here's the error.
  • Ready data
    • Everything worked, and here's the data.

Future cycles states:

  • Recycling data LoadingStage
    • We asked once more, and didn't got the new answer yet. Here's the previous data.
  • Recycling data (FailureStage (Custom error))
    • We asked once more, but the new answer was one of the custom-defined errors instead. Here's the previous data and the current error.
  • Recycling data (FailureStage (Transport error))
    • We asked once more, but the new request got lost on the network-side. Here's the previous data and the current error.
type RecyclingStage transportError customError
= LoadingStage
| FailureStage (RemoteError transportError customError)

Indicates FailureStage and LoadingStage stage when data is/was being fetched.

type alias GraphqlHttpRecyclable error object =
Recyclable (RawError () HttpError) error object

While Recyclable can model any type of errors, the most common one Paack has encountered is when fetching data from a Graphql query, and getting back a GraphqlError. Because of that, GraphqlHttpRecyclable is provided as a useful alias.

Model

First, when initializing a "Model", you will use either:

  • Recyclable.NeverAsked

  • (Recyclable.firstLoading, modelRequestCmd)

firstLoading : Recyclable transportError customError object

It's very common to initialize the model already requesting the data, use firstLoading in this case. Like this:

init : RequestConfig -> ( Model, Cmd Msg )
init requestConfig =
    ( Recyclable.firstLoading
    , modelRequestCmd requestConfig
    )

Update

Then, on "update" you're gonna be using either:

Response transportError customError object
-> Recyclable transportError customError object
-> Recyclable transportError customError object

This is the update routine for when overwriting the current data with a new freshily-fetched response.

update msg model =
    case msg of
        CardFetched response ->
            { model
                | card =
                    Recyclable.mergeResponse response model.card
            }
Recyclable transportError customError object
-> Recyclable transportError customError object

Returns a Recyclable to its loading state. Keeping the information when available.

Response transportError customError object
-> Recyclable transportError customError object

Convert a Response, probably produced from a query result, to a Recyclable value.

NOTE: As this function discards the previous information, in most cases you should be using mergeResponse instead.

Identity crisis

isReady : Recyclable transportError customError object -> Bool

True when Ready _.

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

isError : Recyclable transportError customError object -> Bool

True when _ (Failure _).

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

isCustomError : Recyclable transportError customError object -> Bool

True when _ (Failure (Custom _)).

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

isTransportError : Recyclable transportError customError object -> Bool

True when _ (Failure (Transport _)).

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

isLoading : Recyclable transportError customError object -> Bool

True when _ Loading.

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

isNeverAsked : Recyclable transportError customError object -> Bool

True when NeverAsked.

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

Common transformations

Recyclable transportError customError object
-> Maybe (RemoteError transportError customError)

Transforms Failure error into Just error, and anything else into Nothing.

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

map :
(a -> b)
-> Recyclable transportError customError a
-> Recyclable transportError customError b

Apply a function to the values in Recycling value _ and Ready value. If the data is anything else, the same value will propagate through.

(customError -> a)
-> Recyclable transportError customError object
-> Recyclable transportError a object

Transform a Failure (Custom a) value. If the data is Failure (Custom a), it will be converted. If the data is anything else, the same value will propagate through.

(transportError -> a)
-> Recyclable transportError customError object
-> Recyclable a customError object

Transform a Failure (Transport a) value. If the data is Failure (Transport a), it will be converted. If the data is anything else, the same value will propagate through.

(RemoteError transportError customError -> a)
-> Recyclable transportError customError b
-> Recyclable a a b

Transform a Failure value. If the data is Failure, it will be converted. If the data is anything else, the same value will propagate through.

withDefault : object -> Recyclable transportError customError object -> object

If the recyclable is Success return the value, but if the recyclable is anything else, then return a given default value.

NOTE: This function opposes the purpose of this package by eliminating not aimed states. Always evaluate using a switch-case instead.

merge : object -> Recyclable object object object -> object

For doing pipes instead of switch-case