module Paginated exposing (..) import Dict import Http import Json.Decode import Maybe.Extra import Regex import Url type alias Page a = { prev : Maybe Url.Url , next : Maybe Url.Url , values : List a } empty : Page a empty = { prev = Nothing , next = Nothing , values = [] } expectJson : (Result Http.Error (Page value) -> msg) -> Json.Decode.Decoder value -> Http.Expect msg expectJson toMsg decoder = let linkPattern : Regex.Regex linkPattern = Regex.fromString "<(.*?)>; rel=\"(.*?)\"" |> Maybe.withDefault Regex.never links : String -> Dict.Dict String String links s = let toTuples xs = case xs of [ Just a, Just b ] -> Just ( b, a ) _ -> Nothing in Regex.find linkPattern s |> List.map .submatches |> List.map toTuples |> Maybe.Extra.values |> Dict.fromList in Http.expectStringResponse toMsg <| \response -> case response of Http.BadUrl_ url -> Err (Http.BadUrl url) Http.Timeout_ -> Err Http.Timeout Http.NetworkError_ -> Err Http.NetworkError Http.BadStatus_ metadata _ -> Err (Http.BadStatus metadata.statusCode) Http.GoodStatus_ metadata body -> case Json.Decode.decodeString (Json.Decode.list decoder) body of Ok values -> Ok { prev = Dict.get "link" (Debug.log "headers" metadata.headers) |> Maybe.map links |> Maybe.andThen (Dict.get "prev") |> Maybe.andThen Url.fromString , next = Dict.get "link" metadata.headers |> Maybe.map links |> Maybe.andThen (Dict.get "next") |> Maybe.andThen Url.fromString , values = values } Err err -> Err (Http.BadBody (Json.Decode.errorToString err))