{-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE DerivingVia #-} {-# LANGUAGE DerivingStrategies #-} {- | Haskell types used for testing `elm-street` generated Elm types. -} module Types ( Types , OneType (..) , defaultOneType -- * All test types , Prims (..) , Id (..) , Age (..) , Newtype (..) , NewtypeList (..) , OneConstructor (..) , RequestStatus (..) , User (..) , Guest (..) , UserRequest (..) ) where import Data.Aeson (FromJSON (..), ToJSON (..), Value(..), object, (.=)) import Data.List.NonEmpty (NonEmpty(..)) import Data.Text (Text) import Data.Time.Calendar (fromGregorian) import Data.Time.Clock (UTCTime (..)) import Data.Word (Word32) import Elm (Elm (..), ElmStreet (..), elmNewtype, elmStreetParseJson, elmStreetToJson) import GHC.Generics (Generic) data Prims = Prims { primsUnit :: !() , primsBool :: !Bool , primsChar :: !Char , primsInt :: !Int , primsFloat :: !Double , primsText :: !Text , primsString :: !String , primsTime :: !UTCTime , primsValue :: !Value , primsMaybe :: !(Maybe Word) , primsResult :: !(Either Int Text) , primsPair :: !(Char, Bool) , primsTriple :: !(Char, Bool, [Int]) , primsList :: ![Int] , primsNonEmpty :: !(NonEmpty Int) } deriving (Generic, Eq, Show) deriving (Elm, ToJSON, FromJSON) via ElmStreet Prims newtype Id a = Id { unId :: Text } deriving (Show, Eq) deriving newtype (FromJSON, ToJSON) instance Elm (Id a) where toElmDefinition _ = elmNewtype @Text "Id" "unId" newtype Age = Age { unAge :: Int } deriving (Generic, Eq, Show) deriving anyclass (Elm) deriving newtype (FromJSON, ToJSON) newtype Newtype = Newtype Int deriving stock (Generic, Eq, Show) deriving newtype (FromJSON, ToJSON) deriving anyclass (Elm) newtype NewtypeList = NewtypeList [Int] deriving stock (Generic, Eq, Show) deriving newtype (FromJSON, ToJSON) deriving anyclass (Elm) data OneConstructor = OneConstructor deriving stock (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON OneConstructor where toJSON = elmStreetToJson instance FromJSON OneConstructor where parseJSON = elmStreetParseJson data RequestStatus = Approved | Rejected | Reviewing deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON RequestStatus where toJSON = elmStreetToJson instance FromJSON RequestStatus where parseJSON = elmStreetParseJson data User = User { userId :: !(Id User) , userName :: !Text , userAge :: !Age , userStatus :: !RequestStatus } deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON User where toJSON = elmStreetToJson instance FromJSON User where parseJSON = elmStreetParseJson data Guest = Regular Text Int | Visitor Text | Special (Maybe [Int]) | Blocked deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON Guest where toJSON = elmStreetToJson instance FromJSON Guest where parseJSON = elmStreetParseJson data UserRequest = UserRequest { userRequestIds :: ![Id User] , userRequestLimit :: !Word32 , userRequestExample :: !(Maybe (Either User Guest)) } deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON UserRequest where toJSON = elmStreetToJson instance FromJSON UserRequest where parseJSON = elmStreetParseJson data MyUnit = MyUnit () deriving stock (Show, Eq, Ord, Generic) deriving (Elm, ToJSON, FromJSON) via ElmStreet MyUnit -- | For name clashes testing. data MyResult = Ok | Err Text deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON MyResult where toJSON = elmStreetToJson instance FromJSON MyResult where parseJSON = elmStreetParseJson -- | All test types together in one type to play with. data OneType = OneType { oneTypePrims :: !Prims , oneTypeMyUnit :: !MyUnit , oneTypeMyResult :: !MyResult , oneTypeId :: !(Id OneType) , oneTypeAge :: !Age , oneTypeNewtype :: !Newtype , oneTypeNewtypeList :: !NewtypeList , oneTypeOneConstructor :: !OneConstructor , oneTypeRequestStatus :: !RequestStatus , oneTypeUser :: !User , oneTypeGuests :: ![Guest] , oneTypeUserRequest :: !UserRequest , oneTypeNonEmpty :: !(NonEmpty MyUnit) } deriving (Generic, Eq, Show) deriving anyclass (Elm) instance ToJSON OneType where toJSON = elmStreetToJson instance FromJSON OneType where parseJSON = elmStreetParseJson -- | Type level list of all test types. type Types = '[ Prims , MyUnit , MyResult , Id () , Age , Newtype , NewtypeList , OneConstructor , RequestStatus , User , Guest , UserRequest , OneType ] defaultOneType :: OneType defaultOneType = OneType { oneTypePrims = defaultPrims , oneTypeMyUnit = MyUnit () , oneTypeMyResult = Err "clashing test" , oneTypeId = Id "myId" , oneTypeAge = Age 18 , oneTypeNewtype = Newtype 666 , oneTypeNewtypeList = NewtypeList [123] , oneTypeOneConstructor = OneConstructor , oneTypeRequestStatus = Reviewing , oneTypeUser = User (Id "1") "not-me" (Age 100) Approved , oneTypeGuests = [guestRegular, guestVisitor, guestBlocked] , oneTypeUserRequest = defaultUserRequest , oneTypeNonEmpty = MyUnit () :| [ MyUnit () ] } where defaultPrims :: Prims defaultPrims = Prims { primsUnit = () , primsBool = True , primsChar = 'a' , primsInt = 42 , primsFloat = 36.6 , primsText = "heh" , primsString = "bye" , primsValue = object [ "nullField" .= Null , "boolField" .= True , "numberField" .= (1::Int) , "stringField" .= ("hi"::String) , "arrayField" .= [1::Int,2,3] , "objectField" .= object [] ] , primsTime = UTCTime (fromGregorian 2019 2 22) 0 , primsMaybe = Just 12 , primsResult = Left 666 , primsPair = ('o', False) , primsTriple = ('o', False, [0]) , primsList = [1..5] , primsNonEmpty = 1 :| [] } guestRegular, guestVisitor, guestBlocked :: Guest guestRegular = Regular "nice" 7 guestVisitor = Visitor "new-guest" guestBlocked = Blocked defaultUserRequest :: UserRequest defaultUserRequest = UserRequest { userRequestIds = [Id "1", Id "2"] , userRequestLimit = 123 , userRequestExample = Just (Right Blocked) }