elm-jsonapi icon indicating copy to clipboard operation
elm-jsonapi copied to clipboard

Provide a URL generator module

Open dawehner opened this issue 7 years ago • 6 comments

When you start with more complex endpoints, you end up concatting strings to URLs quite heavily.

It would be kinda nice to have a type safe URL builder specific for jsonapi. Just some idea what kind of data structures could be useful (Note: this is still in flow for my own project)

module App.JsonApiHelper exposing (..)


type alias Url =
    { path : String
    , filter : Maybe (List Filter)
    , include : Maybe (List Include)
    , field : Maybe (List Field)
    , sort : Maybe (List Sort)
    , pager : Maybe (List Pager)
    }


url : String -> Url
url path =
    Url
        { path = path
        , filter = Nothing
        , include = Nothing
        , field = Nothing
        , sort = Nothing
        , pager = Nothing
        }


withFilter : Filter -> Url -> Url
withFilter filter url =
    { url
        | filter =
            Maybe.map url.filter
                |> (::) filter
    }


withInclude : Include -> Url -> Url
withInclude include url =
    { url
        | include =
            Maybe.map url.include
                |> (::) include
    }


withField : Field -> Url -> Url
withField field url =
    { url
        | field =
            Maybe.map url.field
                |> (::) field
    }


withSort : Sort -> Url -> Url
withSort sort url =
    { url
        | sort =
            Maybe.map url.sort
                |> (::) sort
    }


withPager : Pager -> Url -> Url
withPager pager url =
    { url
        | pager =
            Maybe.map url.pager
                |> (::) pager
    }


type alias Sort =
    { keys : List String
    , direction : SortDirection
    }


type SortDirection
    = ASC
    | DESC


sortAsc : String -> Sort
sortAsc string =
    { keys = [ string ]
    , direction = ASC
    }


sortDesc : String -> Sort
sortDesc string =
    { keys = [ string ]
    , direction = DESC
    }


sortAscWithPath : List String -> Sort
sortAscWithPath keys =
    { keys = keys
    , direction = ASC
    }


sortDescWithPath : List String -> Sort
sortDescWithPath keys =
    { keys = keys
    , direction = DESC
    }


type alias Filter =
    { keys : List String
    , operator : Maybe String
    , value : String
    }


filter : List String -> String -> Filter
filter keys value =
    { keys = keys
    , operator = Nothing
    , value = value
    }


type Include
    = Meh2


type Field
    = Meh3


type Pager
    = PagerNumber Int
    | PagerSize Int
    | PagerOffset Int
    | PagerLimit Int
    | PagerCursor Int

dawehner avatar May 21 '17 10:05 dawehner

@dawehner I like this! I'm toying with the idea of unifying around a JsonApi.Http.Request type which would incorporate most of this functionality.

noahzgordon avatar Jun 15 '17 18:06 noahzgordon

One question: how do we conceptually the arbitrarty of the filter parameter?

On Thu, 15 Jun 2017, 19:33 Noah Zachary Gordon, [email protected] wrote:

@dawehner https://github.com/dawehner I like this! I'm toying with the idea of unifying around a JsonApi.Http.Request type which would incorporate most of this functionality.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/noahzgordon/elm-jsonapi/issues/32#issuecomment-308829702, or mute the thread https://github.com/notifications/unsubscribe-auth/AABz7ioL2Zi5VvLfwhuzXpfVnE8jAGwfks5sEXjmgaJpZM4NhkEG .

dawehner avatar Jun 15 '17 20:06 dawehner

@dawehner because "JSON API is agnostic about the strategies supported by a server," we are more or less forced to model the filter as a string.

withFilter : String -> JsonApi.Http.Request -> JsonApi.Http.Request 

noahzgordon avatar Jun 16 '17 07:06 noahzgordon

I'm wondering whether we can somehow pass a type variable along, so implementors can define their own domain type?

dawehner avatar Jun 16 '17 08:06 dawehner

@dawehner I don't think we have enough information about the structure of the string that needs to be produced in order to constrain it in any meaningful way. Literally (and unfortunately) the only thing we know is "it needs to be a string."

Our library could be opinionated about the semantics of the filtering strategy, but I think this would be less true to the spec. For now I'm inclined to leave it as a string. But of course, I could be convinced otherwise if you'd like to keep thinking on it and make a proposal!

noahzgordon avatar Jun 16 '17 08:06 noahzgordon

I'm using https://gist.github.com/e0ipso/1acbced683908ff631e3 right now, so maybe it could make sense to provide its own mechanism for it here?

dawehner avatar Jul 05 '17 12:07 dawehner