Here is a basic version just using URI.Extra.QueryPair with some helpers to parse stuff:
module Main where
import Prelude
import Data.Either (hush)
import Data.Foldable (lookup)
import Data.Int (fromString)
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Class.Console (logShow)
import URI.Extra.QueryPairs (QueryPairs(..))
import URI.Extra.QueryPairs as QP
import URI.Query as Q
main :: Effect Unit
main = do
logShow $ parseQuery "s=str&i=1&b=true"
logShow $ parseQuery "s=abc&i=42&b=false"
logShow $ parseQuery "s=str&i=1"
type Query = { s :: String, i :: Int, b :: Maybe Boolean }
parseQuery :: String -> Maybe Query
parseQuery = Q.fromString >>> QP.parse (QP.keyToString >>> pure) (QP.valueToString >>> pure) >>> hush >=> fromPairs
fromPairs :: QueryPairs String String -> Maybe Query
fromPairs (QueryPairs pairs) = do
s <- join $ lookup "s" pairs
i <- join (lookup "i" pairs) >>= fromString
let b = join (lookup "b" pairs) >>= parseBool
pure { s, i , b}
where
parseBool "true" = Just true
parseBool "false" = Just false
parseBool _ = Nothing
this will output
(Just { b: (Just true), i: 1, s: "str" })
(Just { b: (Just false), i: 42, s: "abc" })
(Just { b: Nothing, i: 1, s: "str" })
for the examples.
The code itself should be rather straight-forward.
Note that QueryPair String String ~ Array String (Maybe String) so the extraction of values is a bit tedious (join)
a version using routing-duplex
If you are fine with installing purescript-routing-duplex you can use the parser in there to help you out quite a bit - that's the one I'd use (especially when you probably want to parse routes with parameters anyway):
module Main where
import Prelude
import Data.Either (hush)
import Data.Maybe (Maybe)
import Effect (Effect)
import Effect.Class.Console (logShow)
import Routing.Duplex as R
main :: Effect Unit
main = do
logShow $ parseQuery "s=str&i=1&b=true"
logShow $ parseQuery "s=abc&i=42&b=false"
logShow $ parseQuery "s=str&i=1"
type Query = { s :: String, i :: Int, b :: Maybe Boolean }
parseQuery :: String -> Maybe Query
parseQuery s = hush $ R.parse parser ("?" <> s)
where
parser =
R.params
{ s: R.string
, i: R.int
, b: R.optional <<< R.boolean
}