{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE NoImplicitPrelude #-}

module Data.Morpheus.Types.ID
  ( ID (..),
  )
where

import Data.Aeson (FromJSON (..), ToJSON (..))
import Data.Morpheus.Types.GQLScalar
  ( GQLScalar (..),
    scalarFromJSON,
    scalarToJSON,
  )
import Data.Morpheus.Types.Internal.AST
  ( ScalarValue (..),
  )
import Data.Text (pack)
import Relude

-- | default GraphQL type,
-- parses only 'String' and 'Int' values,
-- serialized always as 'String'
newtype ID = ID
  { ID -> Text
unpackID :: Text
  }
  deriving (Int -> ID -> ShowS
[ID] -> ShowS
ID -> String
(Int -> ID -> ShowS)
-> (ID -> String) -> ([ID] -> ShowS) -> Show ID
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ID] -> ShowS
$cshowList :: [ID] -> ShowS
show :: ID -> String
$cshow :: ID -> String
showsPrec :: Int -> ID -> ShowS
$cshowsPrec :: Int -> ID -> ShowS
Show, (forall x. ID -> Rep ID x)
-> (forall x. Rep ID x -> ID) -> Generic ID
forall x. Rep ID x -> ID
forall x. ID -> Rep ID x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep ID x -> ID
$cfrom :: forall x. ID -> Rep ID x
Generic, ID -> ID -> Bool
(ID -> ID -> Bool) -> (ID -> ID -> Bool) -> Eq ID
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ID -> ID -> Bool
$c/= :: ID -> ID -> Bool
== :: ID -> ID -> Bool
$c== :: ID -> ID -> Bool
Eq)

instance GQLScalar ID where
  parseValue :: ScalarValue -> Either Text ID
parseValue (Int Int
x) = ID -> Either Text ID
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ID
ID (Text -> ID) -> Text -> ID
forall a b. (a -> b) -> a -> b
$ String -> Text
pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ Int -> String
forall b a. (Show a, IsString b) => a -> b
show Int
x)
  parseValue (String Text
x) = ID -> Either Text ID
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> ID
ID Text
x)
  parseValue ScalarValue
_ = Text -> Either Text ID
forall a b. a -> Either a b
Left Text
"ID can only be String or number"
  serialize :: ID -> ScalarValue
serialize (ID Text
x) = Text -> ScalarValue
String Text
x

instance ToJSON ID where
  toJSON :: ID -> Value
toJSON = ID -> Value
forall a. GQLScalar a => a -> Value
scalarToJSON

instance FromJSON ID where
  parseJSON :: Value -> Parser ID
parseJSON = Value -> Parser ID
forall (m :: * -> *) a.
(Monad m, MonadFail m, GQLScalar a) =>
Value -> m a
scalarFromJSON