{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE UndecidableInstances #-}

module Web.Hyperbole.Data.QueryData where

import Data.Aeson (Value (Null))
import Data.ByteString (ByteString)
import Data.Default (Default (..))
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as M
import Data.Maybe (fromMaybe)
import Data.String.Conversions (cs)
import Data.Text (Text, pack)
import GHC.Exts (IsList (..))
import GHC.Generics
import Network.HTTP.Types (Query, QueryItem, renderQuery)
import Network.HTTP.Types qualified as HTTP
import Web.Hyperbole.Data.Encoded (decodeParam, encodeParam)
import Web.Hyperbole.Data.Param
import Prelude hiding (lookup)


-- | Key-value store for query params and sessions
newtype QueryData = QueryData (Map Param ParamValue)
  deriving (Int -> QueryData -> ShowS
[QueryData] -> ShowS
QueryData -> String
(Int -> QueryData -> ShowS)
-> (QueryData -> String)
-> ([QueryData] -> ShowS)
-> Show QueryData
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> QueryData -> ShowS
showsPrec :: Int -> QueryData -> ShowS
$cshow :: QueryData -> String
show :: QueryData -> String
$cshowList :: [QueryData] -> ShowS
showList :: [QueryData] -> ShowS
Show)
  deriving newtype (Semigroup QueryData
QueryData
Semigroup QueryData =>
QueryData
-> (QueryData -> QueryData -> QueryData)
-> ([QueryData] -> QueryData)
-> Monoid QueryData
[QueryData] -> QueryData
QueryData -> QueryData -> QueryData
forall a.
Semigroup a =>
a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
$cmempty :: QueryData
mempty :: QueryData
$cmappend :: QueryData -> QueryData -> QueryData
mappend :: QueryData -> QueryData -> QueryData
$cmconcat :: [QueryData] -> QueryData
mconcat :: [QueryData] -> QueryData
Monoid, NonEmpty QueryData -> QueryData
QueryData -> QueryData -> QueryData
(QueryData -> QueryData -> QueryData)
-> (NonEmpty QueryData -> QueryData)
-> (forall b. Integral b => b -> QueryData -> QueryData)
-> Semigroup QueryData
forall b. Integral b => b -> QueryData -> QueryData
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
$c<> :: QueryData -> QueryData -> QueryData
<> :: QueryData -> QueryData -> QueryData
$csconcat :: NonEmpty QueryData -> QueryData
sconcat :: NonEmpty QueryData -> QueryData
$cstimes :: forall b. Integral b => b -> QueryData -> QueryData
stimes :: forall b. Integral b => b -> QueryData -> QueryData
Semigroup)


instance IsList QueryData where
  type Item QueryData = (Param, ParamValue)
  fromList :: [Item QueryData] -> QueryData
fromList = Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> ([(Param, ParamValue)] -> Map Param ParamValue)
-> [(Param, ParamValue)]
-> QueryData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [(Param, ParamValue)] -> Map Param ParamValue
[Item (Map Param ParamValue)] -> Map Param ParamValue
forall l. IsList l => [Item l] -> l
fromList
  toList :: QueryData -> [Item QueryData]
toList (QueryData Map Param ParamValue
m) = Map Param ParamValue -> [Item (Map Param ParamValue)]
forall l. IsList l => l -> [Item l]
toList Map Param ParamValue
m


singleton :: (ToParam a) => Param -> a -> QueryData
singleton :: forall a. ToParam a => Param -> a -> QueryData
singleton Param
key a
a = Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> Map Param ParamValue -> QueryData
forall a b. (a -> b) -> a -> b
$ Param -> ParamValue -> Map Param ParamValue
forall k a. k -> a -> Map k a
M.singleton Param
key (a -> ParamValue
forall a. ToParam a => a -> ParamValue
toParam a
a)


insert :: (ToParam a) => Param -> a -> QueryData -> QueryData
insert :: forall a. ToParam a => Param -> a -> QueryData -> QueryData
insert Param
p a
a (QueryData Map Param ParamValue
m) =
  Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> Map Param ParamValue -> QueryData
forall a b. (a -> b) -> a -> b
$ Param -> ParamValue -> Map Param ParamValue -> Map Param ParamValue
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Param
p (a -> ParamValue
forall a. ToParam a => a -> ParamValue
toParam a
a) Map Param ParamValue
m


insertAll :: (ToQuery a) => a -> QueryData -> QueryData
insertAll :: forall a. ToQuery a => a -> QueryData -> QueryData
insertAll a
a (QueryData Map Param ParamValue
m) =
  let QueryData Map Param ParamValue
kvs = a -> QueryData
forall a. ToQuery a => a -> QueryData
toQuery a
a
   in Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> Map Param ParamValue -> QueryData
forall a b. (a -> b) -> a -> b
$ Map Param ParamValue
-> Map Param ParamValue -> Map Param ParamValue
forall k a. Ord k => Map k a -> Map k a -> Map k a
M.union Map Param ParamValue
kvs Map Param ParamValue
m


delete :: Param -> QueryData -> QueryData
delete :: Param -> QueryData -> QueryData
delete Param
p (QueryData Map Param ParamValue
m) =
  Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> Map Param ParamValue -> QueryData
forall a b. (a -> b) -> a -> b
$ Param -> Map Param ParamValue -> Map Param ParamValue
forall k a. Ord k => k -> Map k a -> Map k a
M.delete Param
p Map Param ParamValue
m


lookup :: (FromParam a) => Param -> QueryData -> Maybe a
lookup :: forall a. FromParam a => Param -> QueryData -> Maybe a
lookup Param
k (QueryData Map Param ParamValue
m) = do
  ParamValue
t <- Param -> Map Param ParamValue -> Maybe ParamValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Param
k Map Param ParamValue
m
  (String -> Maybe a) -> (a -> Maybe a) -> Either String a -> Maybe a
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Maybe a -> String -> Maybe a
forall a b. a -> b -> a
const Maybe a
forall a. Maybe a
Nothing) a -> Maybe a
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String a -> Maybe a) -> Either String a -> Maybe a
forall a b. (a -> b) -> a -> b
$ ParamValue -> Either String a
forall a. FromParam a => ParamValue -> Either String a
parseParam ParamValue
t


require :: (FromParam a) => Param -> QueryData -> Either String a
require :: forall a. FromParam a => Param -> QueryData -> Either String a
require Param
p (QueryData Map Param ParamValue
m) = do
  case Param -> Map Param ParamValue -> Maybe ParamValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Param
p Map Param ParamValue
m of
    Maybe ParamValue
Nothing -> String -> Either String a
forall a b. a -> Either a b
Left (String -> Either String a) -> String -> Either String a
forall a b. (a -> b) -> a -> b
$ String
"Missing Key: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a b. ConvertibleStrings a b => a -> b
cs Param
p.text
    Just ParamValue
val -> ParamValue -> Either String a
forall a. FromParam a => ParamValue -> Either String a
parseParam ParamValue
val


filterKey :: (Param -> Bool) -> QueryData -> QueryData
filterKey :: (Param -> Bool) -> QueryData -> QueryData
filterKey Param -> Bool
p (QueryData Map Param ParamValue
m) =
  Map Param ParamValue -> QueryData
QueryData (Map Param ParamValue -> QueryData)
-> Map Param ParamValue -> QueryData
forall a b. (a -> b) -> a -> b
$ (Param -> ParamValue -> Bool)
-> Map Param ParamValue -> Map Param ParamValue
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
M.filterWithKey (\Param
k ParamValue
_ -> Param -> Bool
p Param
k) Map Param ParamValue
m


member :: Param -> QueryData -> Bool
member :: Param -> QueryData -> Bool
member Param
k (QueryData Map Param ParamValue
qd) = Param -> Map Param ParamValue -> Bool
forall k a. Ord k => k -> Map k a -> Bool
M.member Param
k Map Param ParamValue
qd


elems :: QueryData -> [ParamValue]
elems :: QueryData -> [ParamValue]
elems (QueryData Map Param ParamValue
m) = Map Param ParamValue -> [ParamValue]
forall k a. Map k a -> [a]
M.elems Map Param ParamValue
m


render :: QueryData -> ByteString
render :: QueryData -> ByteString
render QueryData
qd =
  Bool -> Query -> ByteString
renderQuery Bool
False (Query -> Query
forall a. QueryLike a => a -> Query
HTTP.toQuery (Query -> Query) -> Query -> Query
forall a b. (a -> b) -> a -> b
$ QueryData -> Query
fromQueryData QueryData
qd)


parse :: ByteString -> QueryData
parse :: ByteString -> QueryData
parse =
  -- urlDecode True
  Query -> QueryData
queryData (Query -> QueryData)
-> (ByteString -> Query) -> ByteString -> QueryData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Query
HTTP.parseQuery


queryData :: Query -> QueryData
queryData :: Query -> QueryData
queryData Query
q =
  [Item QueryData] -> QueryData
forall l. IsList l => [Item l] -> l
fromList ([Item QueryData] -> QueryData) -> [Item QueryData] -> QueryData
forall a b. (a -> b) -> a -> b
$ (QueryItem -> (Param, ParamValue))
-> Query -> [(Param, ParamValue)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap QueryItem -> (Param, ParamValue)
fromQueryItem Query
q
 where
  fromQueryItem :: QueryItem -> (Param, ParamValue)
  fromQueryItem :: QueryItem -> (Param, ParamValue)
fromQueryItem (ByteString
key, Maybe ByteString
mval) =
    (Text -> Param
Param (ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
key), Maybe ByteString -> ParamValue
fromParam Maybe ByteString
mval)

  fromParam :: Maybe ByteString -> ParamValue
  fromParam :: Maybe ByteString -> ParamValue
fromParam Maybe ByteString
Nothing = Value -> ParamValue
forall a. ToJSON a => a -> ParamValue
jsonParam Value
Null
  fromParam (Just ByteString
t) = Text -> ParamValue
decodeParam (ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
t)


fromQueryData :: QueryData -> Query
fromQueryData :: QueryData -> Query
fromQueryData QueryData
q =
  ((Param, ParamValue) -> QueryItem)
-> [(Param, ParamValue)] -> Query
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Param, ParamValue) -> QueryItem
toQueryItem ([(Param, ParamValue)] -> Query) -> [(Param, ParamValue)] -> Query
forall a b. (a -> b) -> a -> b
$ QueryData -> [Item QueryData]
forall l. IsList l => l -> [Item l]
toList QueryData
q
 where
  toQueryItem :: (Param, ParamValue) -> QueryItem
  toQueryItem :: (Param, ParamValue) -> QueryItem
toQueryItem (Param Text
prm, ParamValue
pval) =
    (Text -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs Text
prm, ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString) -> ByteString -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ParamValue -> ByteString
toQueryValue ParamValue
pval)

  toQueryValue :: ParamValue -> ByteString
  toQueryValue :: ParamValue -> ByteString
toQueryValue = Text -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs (Text -> ByteString)
-> (ParamValue -> Text) -> ParamValue -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParamValue -> Text
encodeParam


{- | Decode a type from a 'QueryData'. Missing fields are set to 'Data.Default.def'

@
data Filters = Filters
  { active :: Bool
  , term :: Text
  }
  deriving (Generic, Eq, 'FromQuery', 'ToQuery')
@

>>> parseQuery $ QueryData.parse "active=true&search=asdf"
Right (Filters True "asdf")

>>> parseQuery $ QueryData.parse "search=asdf"
Right (Filters False "asdf")
-}
class FromQuery a where
  parseQuery :: QueryData -> Either String a
  default parseQuery :: (Generic a, GFromQuery (Rep a)) => QueryData -> Either String a
  parseQuery QueryData
q = Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Rep a Any -> a) -> Either String (Rep a Any) -> Either String a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryData -> Either String (Rep a Any)
forall p. QueryData -> Either String (Rep a p)
forall {k} (f :: k -> *) (p :: k).
GFromQuery f =>
QueryData -> Either String (f p)
gParseQuery QueryData
q


instance FromQuery QueryData where
  parseQuery :: QueryData -> Either String QueryData
parseQuery = QueryData -> Either String QueryData
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure


{- | A page can store state in the browser 'query' string. ToQuery and 'FromQuery' control how a datatype is encoded to a full query string

@
data Filters = Filters
  { active :: Bool
  , term :: Text
  }
  deriving (Generic, Eq, 'FromQuery', 'ToQuery')
@

>>> QueryData.render $ toQuery $ Filter True "asdf"
"active=true&search=asdf"

If the value of a field is the same as 'Default', it will be omitted from the query string

>>> QueryData.render $ toQuery $ Filter True ""
"active=true"

>>> QueryData.render $ toQuery $ Filter False ""
""
-}
class ToQuery a where
  toQuery :: a -> QueryData
  default toQuery :: (Generic a, GToQuery (Rep a)) => a -> QueryData
  toQuery = Rep a Any -> QueryData
forall p. Rep a p -> QueryData
forall {k} (f :: k -> *) (p :: k). GToQuery f => f p -> QueryData
gToQuery (Rep a Any -> QueryData) -> (a -> Rep a Any) -> a -> QueryData
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Rep a Any
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from


instance ToQuery QueryData where
  toQuery :: QueryData -> QueryData
toQuery = QueryData -> QueryData
forall a. a -> a
id


instance ToQuery Query where
  toQuery :: Query -> QueryData
toQuery = Query -> QueryData
queryData


-- | Generic decoding of records from a Query
class GFromQuery f where
  gParseQuery :: QueryData -> Either String (f p)


instance (GFromQuery f, GFromQuery g) => GFromQuery (f :*: g) where
  gParseQuery :: forall (p :: k). QueryData -> Either String ((:*:) f g p)
gParseQuery QueryData
q = do
    f p
a <- QueryData -> Either String (f p)
forall (p :: k). QueryData -> Either String (f p)
forall {k} (f :: k -> *) (p :: k).
GFromQuery f =>
QueryData -> Either String (f p)
gParseQuery QueryData
q
    g p
b <- QueryData -> Either String (g p)
forall (p :: k). QueryData -> Either String (g p)
forall {k} (f :: k -> *) (p :: k).
GFromQuery f =>
QueryData -> Either String (f p)
gParseQuery QueryData
q
    (:*:) f g p -> Either String ((:*:) f g p)
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((:*:) f g p -> Either String ((:*:) f g p))
-> (:*:) f g p -> Either String ((:*:) f g p)
forall a b. (a -> b) -> a -> b
$ f p
a f p -> g p -> (:*:) f g p
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: g p
b


instance (GFromQuery f) => GFromQuery (M1 D d f) where
  gParseQuery :: forall (p :: k). QueryData -> Either String (M1 D d f p)
gParseQuery QueryData
q = f p -> M1 D d f p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (f p -> M1 D d f p)
-> Either String (f p) -> Either String (M1 D d f p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryData -> Either String (f p)
forall (p :: k). QueryData -> Either String (f p)
forall {k} (f :: k -> *) (p :: k).
GFromQuery f =>
QueryData -> Either String (f p)
gParseQuery QueryData
q


instance (GFromQuery f) => GFromQuery (M1 C c f) where
  gParseQuery :: forall (p :: k). QueryData -> Either String (M1 C c f p)
gParseQuery QueryData
q = f p -> M1 C c f p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (f p -> M1 C c f p)
-> Either String (f p) -> Either String (M1 C c f p)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryData -> Either String (f p)
forall (p :: k). QueryData -> Either String (f p)
forall {k} (f :: k -> *) (p :: k).
GFromQuery f =>
QueryData -> Either String (f p)
gParseQuery QueryData
q


instance {-# OVERLAPPABLE #-} (Selector s, FromParam a, Default a) => GFromQuery (M1 S s (K1 R a)) where
  gParseQuery :: forall (p :: k). QueryData -> Either String (M1 S s (K1 R a) p)
gParseQuery QueryData
q = do
    let s :: String
s = M1 S s (K1 R (Any a)) Any -> String
forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
       (f :: k1 -> *) (a :: k1).
Selector s =>
t s f a -> String
forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
       (a :: k1).
t s f a -> String
selName (M1 S s (K1 R (f a)) p
forall {k} {f :: * -> *} {p :: k}. M1 S s (K1 R (f a)) p
forall a. HasCallStack => a
undefined :: M1 S s (K1 R (f a)) p)
    let mval :: Maybe a
mval = Param -> QueryData -> Maybe a
forall a. FromParam a => Param -> QueryData -> Maybe a
lookup (Text -> Param
Param (Text -> Param) -> Text -> Param
forall a b. (a -> b) -> a -> b
$ String -> Text
pack String
s) QueryData
q
    M1 S s (K1 R a) p -> Either String (M1 S s (K1 R a) p)
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (M1 S s (K1 R a) p -> Either String (M1 S s (K1 R a) p))
-> M1 S s (K1 R a) p -> Either String (M1 S s (K1 R a) p)
forall a b. (a -> b) -> a -> b
$ K1 R a p -> M1 S s (K1 R a) p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (K1 R a p -> M1 S s (K1 R a) p) -> K1 R a p -> M1 S s (K1 R a) p
forall a b. (a -> b) -> a -> b
$ a -> K1 R a p
forall k i c (p :: k). c -> K1 i c p
K1 (a -> K1 R a p) -> a -> K1 R a p
forall a b. (a -> b) -> a -> b
$ a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
forall a. Default a => a
def Maybe a
mval


-- Text doesn't have a default instance. Annoying
instance {-# OVERLAPS #-} (Selector s) => GFromQuery (M1 S s (K1 R Text)) where
  gParseQuery :: forall (p :: k). QueryData -> Either String (M1 S s (K1 R Text) p)
gParseQuery QueryData
q = do
    let s :: String
s = M1 S s (K1 R (Any Any)) Any -> String
forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
       (f :: k1 -> *) (a :: k1).
Selector s =>
t s f a -> String
forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
       (a :: k1).
t s f a -> String
selName (M1 S s (K1 R (f a)) p
forall {k} {k} {f :: k -> *} {a :: k} {p :: k}.
M1 S s (K1 R (f a)) p
forall a. HasCallStack => a
undefined :: M1 S s (K1 R (f a)) p)
    let mval :: Maybe Text
mval = Param -> QueryData -> Maybe Text
forall a. FromParam a => Param -> QueryData -> Maybe a
lookup (Text -> Param
Param (Text -> Param) -> Text -> Param
forall a b. (a -> b) -> a -> b
$ String -> Text
pack String
s) QueryData
q
    M1 S s (K1 R Text) p -> Either String (M1 S s (K1 R Text) p)
forall a. a -> Either String a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (M1 S s (K1 R Text) p -> Either String (M1 S s (K1 R Text) p))
-> M1 S s (K1 R Text) p -> Either String (M1 S s (K1 R Text) p)
forall a b. (a -> b) -> a -> b
$ K1 R Text p -> M1 S s (K1 R Text) p
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (K1 R Text p -> M1 S s (K1 R Text) p)
-> K1 R Text p -> M1 S s (K1 R Text) p
forall a b. (a -> b) -> a -> b
$ Text -> K1 R Text p
forall k i c (p :: k). c -> K1 i c p
K1 (Text -> K1 R Text p) -> Text -> K1 R Text p
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
"" Maybe Text
mval


-- | Generic encoding of records to a Query
class GToQuery f where
  gToQuery :: f p -> QueryData


instance (GToQuery f, GToQuery g) => GToQuery (f :*: g) where
  gToQuery :: forall (p :: k). (:*:) f g p -> QueryData
gToQuery (f p
f :*: g p
g) = f p -> QueryData
forall (p :: k). f p -> QueryData
forall {k} (f :: k -> *) (p :: k). GToQuery f => f p -> QueryData
gToQuery f p
f QueryData -> QueryData -> QueryData
forall a. Semigroup a => a -> a -> a
<> g p -> QueryData
forall (p :: k). g p -> QueryData
forall {k} (f :: k -> *) (p :: k). GToQuery f => f p -> QueryData
gToQuery g p
g


instance (GToQuery f) => GToQuery (M1 D d f) where
  gToQuery :: forall (p :: k). M1 D d f p -> QueryData
gToQuery (M1 f p
f) = f p -> QueryData
forall (p :: k). f p -> QueryData
forall {k} (f :: k -> *) (p :: k). GToQuery f => f p -> QueryData
gToQuery f p
f


instance (GToQuery f) => GToQuery (M1 C d f) where
  gToQuery :: forall (p :: k). M1 C d f p -> QueryData
gToQuery (M1 f p
f) = f p -> QueryData
forall (p :: k). f p -> QueryData
forall {k} (f :: k -> *) (p :: k). GToQuery f => f p -> QueryData
gToQuery f p
f


instance {-# OVERLAPPABLE #-} (Selector s, ToParam a, Eq a, Default a) => GToQuery (M1 S s (K1 R a)) where
  gToQuery :: forall (p :: k). M1 S s (K1 R a) p -> QueryData
gToQuery (M1 (K1 a
a))
    | a
a a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
forall a. Default a => a
def = QueryData
forall a. Monoid a => a
mempty
    | Bool
otherwise =
        let sel :: Param
sel = Text -> Param
Param (Text -> Param) -> Text -> Param
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ M1 S s (K1 R (Any a)) Any -> String
forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
       (f :: k1 -> *) (a :: k1).
Selector s =>
t s f a -> String
forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
       (a :: k1).
t s f a -> String
selName (M1 S s (K1 R (f a)) p
forall {k} {f :: * -> *} {p :: k}. M1 S s (K1 R (f a)) p
forall a. HasCallStack => a
undefined :: M1 S s (K1 R (f a)) p)
         in Param -> a -> QueryData
forall a. ToParam a => Param -> a -> QueryData
singleton Param
sel a
a


-- Special case for Text, which has no Default instance
instance {-# OVERLAPS #-} (Selector s) => GToQuery (M1 S s (K1 R Text)) where
  gToQuery :: forall (p :: k). M1 S s (K1 R Text) p -> QueryData
gToQuery (M1 (K1 Text
a))
    | Text
a Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"" = QueryData
forall a. Monoid a => a
mempty
    | Bool
otherwise =
        let sel :: Param
sel = Text -> Param
Param (Text -> Param) -> Text -> Param
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ M1 S s (K1 R (Any Any)) Any -> String
forall {k} (s :: k) k1 (t :: k -> (k1 -> *) -> k1 -> *)
       (f :: k1 -> *) (a :: k1).
Selector s =>
t s f a -> String
forall k1 (t :: Meta -> (k1 -> *) -> k1 -> *) (f :: k1 -> *)
       (a :: k1).
t s f a -> String
selName (M1 S s (K1 R (f a)) p
forall {k} {k} {f :: k -> *} {a :: k} {p :: k}.
M1 S s (K1 R (f a)) p
forall a. HasCallStack => a
undefined :: M1 S s (K1 R (f a)) p)
         in Param -> Text -> QueryData
forall a. ToParam a => Param -> a -> QueryData
singleton Param
sel Text
a

-- instance {-# OVERLAPS #-} (Selector s, ToParam a, Eq a) => GToQuery (M1 S s (K1 R [a])) where
--   gToQuery (M1 (K1 a))
--     | a == [] = mempty
--     | otherwise =
--         let sel = Param $ pack $ selName (undefined :: M1 S s (K1 R (f a)) p)
--          in singleton sel $ Plusses a