domaindriven-0.5.0: src/DomainDriven/Server/Types.hs
module DomainDriven.Server.Types where
import Control.Monad.State
import Data.Function (on)
import Data.Generics.Product
import Data.List qualified as L
import Data.Set (Set)
import GHC.Generics (Generic)
import Language.Haskell.TH
import Lens.Micro ((^.))
import Prelude
-- Contains infromatiotion of how the API should look, gathered from the Action GADT.
data ApiSpec = ApiSpec
{ gadtName :: GadtName
, gadtType :: GadtType
-- ^ Name of the GADT representing the command
, allVarBindings :: VarBindings
, endpoints :: [ApiPiece]
-- ^ Endpoints created from the constructors of the GADT
, options :: ApiOptions
-- ^ The setting to use when generating part of the API
}
deriving (Show, Generic)
data VarBindings = VarBindings
{ paramPart :: Name
, method :: Name
, return :: Name
, extra :: [TyVarBndr ()]
}
deriving (Show, Generic, Eq)
data ApiOptions = ApiOptions
{ renameConstructor :: String -> String
, typenameSeparator :: String
, bodyNameBase :: Maybe String
}
deriving (Generic)
defaultApiOptions :: ApiOptions
defaultApiOptions =
ApiOptions
{ renameConstructor =
\s -> case L.splitAt (on (-) L.length s "Action") s of
(x, "Action") -> x
_ -> s
, typenameSeparator = "_"
, bodyNameBase = Nothing
}
instance Show ApiOptions where
show o =
"ApiOptions {renameConstructor = ***, typenameSeparator = \""
<> o
^. field @"typenameSeparator"
<> "\"}"
data Mutability
= Mutable
| Immutable
deriving (Show, Eq)
data ApiPiece
= Endpoint
ConstructorName
ConstructorArgs
VarBindings
HandlerSettings
Mutability
EpReturnType
| SubApi ConstructorName ConstructorArgs ApiSpec
deriving (Show, Generic)
data HandlerSettings = HandlerSettings
{ contentTypes :: Type
, verb :: Type
}
deriving (Show, Generic, Eq)
newtype ConstructorName = ConstructorName Name deriving (Show, Generic, Eq)
newtype EpReturnType = EpReturnType Type deriving (Show, Generic, Eq)
newtype GadtName = GadtName Name deriving (Show, Generic, Eq)
newtype GadtType = GadtType Type deriving (Show, Generic, Eq)
newtype UrlSegment = UrlSegment String deriving (Show, Generic, Eq)
newtype ConstructorArgs = ConstructorArgs [(String, Type)] deriving (Show, Generic, Eq)
newtype Runner = Runner Type deriving (Show, Generic, Eq)
-- | Carries information regarding how the API looks at the place we're currently at.
data ServerInfo = ServerInfo
{ baseGadt :: GadtName
-- ^ Use as a prefix of all types
, currentGadt :: GadtName
, parentConstructors :: [ConstructorName]
-- ^ To create good names without conflict
, prefixSegments :: [UrlSegment]
-- ^ Used to give a good name to the request body
, options :: ApiOptions
-- ^ The current options
}
deriving (Show, Generic)
data ServerGenState = ServerGenState
{ info :: ServerInfo
, usedParamNames :: Set String
}
deriving (Show, Generic)
newtype ServerGenM a = ServerGenM {unServerGenM :: StateT ServerGenState Q a}
deriving newtype (Functor, Applicative, Monad, MonadState ServerGenState, MonadFail)
data Pmatch = Pmatch
{ paramPart :: Name
, paramName :: String
, paramType :: Type
}
deriving (Show, Generic)
data ConstructorMatch = ConstructorMatch
{ xParam :: Name
-- ^ Of kind ParamPart
, constructorName :: Name
, parameters :: [Pmatch]
, finalType :: FinalConstructorTypeMatch
}
deriving (Show, Generic)
data SubActionMatch = SubActionMatch
{ constructorName :: Name
, parameters :: [Pmatch]
, subActionName :: Name
, subActionType :: Type
}
deriving (Show, Generic)
data SubActionTypeMatch = SubActionTypeMatch
deriving (Show, Generic)
data FinalConstructorTypeMatch = FinalConstructorTypeMatch
{ requestType :: RequestTypeMatch
, returnType :: Type
}
deriving (Show, Generic)
data RequestTypeMatch = RequestTypeMatch
{ accessType :: Type
, contentTypes :: Type
, verb :: Type
}
deriving (Show, Generic)