sporto / qs / QS

Parse an manipulate query strings

Types


type alias Query =
Dict String OneOrMany

A parsed query string

"?a=x&b[]=1&b=2"
    == Dict.fromList
        [ ( "a", One <| "x" )
        , ( "b", Many [ "1", "2" ] )
        ]


type OneOrMany
    = One String
    | Many (List String)

A query value can be a unique value (One) e.g.

a =
    1
        == One "1"

Or it can be a list (Many) e.g.

a[]=1&a[]=2

==

Many [ "1", "2" ]

Parse and Serialize

parse : Config -> String -> Query

Parse a query string. This loosely follows https://github.com/ljharb/qs

QS.parse
    QS.config
    "?a=1&b=x"
    == Dict.fromList [ ( "a", One "1" ), ( "b", One "x" ) ]

serialize : Config -> Query -> String

Serialize the query. This follows https://github.com/ljharb/qs serialization.

QS.serialize Qs.config <|
    Dict.fromList [ ( "a", QueryString "1" ), ( "b", QueryString "2" ) ]
        == "?a=1&b=2"

List are serialized by adding []

QS.serialize Qs.config <|
    Dict.fromList [ ( "a", QueryStringList [ "1", "2" ] ) ]
        == "?a%5B%5D=1&a%5B%5D=2" (equivalent to "?a[]=1&a[]=2")

If your don't want to encode [] use encodeBrackets False.

QS.serialize
    (Qs.config |> encodeBrackets False) ...

==

"?a[]=1&a[]=2"

However brackets in the value are always encoded.

Config


type Config

Opaque configuration type

config : Config

Get a default configuration

encodeBrackets =
    True

addQuestionMark : Basics.Bool -> Config -> Config

Wherever to add ? when serializing. Default is True.

QS.serialize Qs.config query
    == "?a[]=1"

QS.serialize (Qs.config |> Qs.addQuestionMark False) query
    == "a[]=1"

encodeBrackets : Basics.Bool -> Config -> Config

Wherever to encode brackets or not

QS.serialize (Qs.config |> Qs.encodeBrackets False) query
    == "?a[]=1&a[]=2"

Decode and Encode

decoder : Json.Decode.Decoder Query

Decode JSON into a QS.Query

json =
    """{"a":["x", 1, true]}"""

Decode.decodeString QS.decoder json

===

Dict.fromList [ ( "a", Many [ "x", "1", "true" ] ) ]

This decoder doesn't handle nested values. Nested data will fail the decoder.

encode : Query -> Json.Encode.Value

Encode a QS.Query to a JSON value

query =
    Many [ "x", "true" ] )

encodedQuery =
    QS.encode query

Encode.encode 0 encodedQuery

==

"""{"a":["x",true]}"""

Transform

empty : Query

Get an empty QS.Query

get : String -> Query -> Maybe OneOrMany

Get a value from the query

QS.get "a" query
    == Maybe (One "1")

getAsStringList : String -> Query -> List String

Get values from the query as a list of strings (regardless if one or many). If keys are not present this defaults to an empty list

query =
    Dict.fromList [ ("a", Many ["true", "1"]) ]

QS.getAsStringList "a" query

==

["true", "1"]

getAsMaybeStringList : String -> Query -> Maybe (List String)

Get values from the query as a maybe list of strings. If keys are not present this returns a Nothing

query =
    Dict.fromList [ ("a", Many ["true", "1"]) ]

QS.getAsStringList "a" query

==

Just ["true", "1"]

has : String -> Query -> Basics.Bool

Tell if the query has the given key (regardless if one or many)

query =
    Dict.fromList [ ("a", One "true" ]

QS.has "a" query == True

set : String -> OneOrMany -> Query -> Query

Set a value in the query

QS.set "a" (One <| Str "1") query

setOne : String -> String -> Query -> Query

Set a unique value in the query

QS.setOne "a" "1" query

setStr : String -> String -> Query -> Query

Set a string value in the query

QS.setStr "a" "1" Qs.empty
    == Dict.fromList [ ( "a", One "1" ) ]

setBool : String -> Basics.Bool -> Query -> Query

Set a boolean value in the query

QS.setBool "a" True Qs.empty
    == Dict.fromList [ ( "a", One "true" ) ]

setNum : String -> Basics.Float -> Query -> Query

Set a numeric value in the query

QS.setBool "a" 2 Qs.empty
    == Dict.fromList [ ( "a", One "2" ) ]

setList : String -> List String -> Query -> Query

Set a list of values in the query

QS.setList "a" [ "1", "true" ] query

setListStr : String -> List String -> Query -> Query

Set a list of string values in the query

QS.setListStr "a" ["1", "x"] Qs.empty

==

Dict.fromList [ ("a", Many [ "1", "x" ] ]

setListBool : String -> List Basics.Bool -> Query -> Query

Set a list of boolean values in the query

QS.setListBool "a" [ True, False ] Qs.empty

setListNum : String -> List Basics.Float -> Query -> Query

Set a list of numeric values in the query

QS.setListNum "a" [ 2, 3 ] Qs.empty

push : String -> String -> Query -> Query

Adds one value to a list

QS.push "a" "2" Qs.empty

pushBool : String -> Basics.Bool -> Query -> Query

Add one boolean to a list

pushNum : String -> Basics.Float -> Query -> Query

Add one number to a list

pushStr : String -> String -> Query -> Query

Add one string to a list

merge : Query -> Query -> Query

Merge two Querys. Values in the first override values in the second.

remove : String -> Query -> Query

Remove a key from the query