-- | Newtype wrappers for route DSL module Mig.Core.Types.Route ( -- * inputs Body (..), Query (..), QueryFlag (..), Optional (..), Capture (..), Header (..), OptionalHeader (..), Cookie (..), PathInfo (..), FullPathInfo (..), RawRequest (..), IsSecure (..), -- * outputs Send (..), Get, Post, Put, Delete, Options, Head, Patch, Trace, -- ** Method tags IsMethod (..), GET, POST, PUT, DELETE, OPTIONS, HEAD, PATCH, TRACE, ) where import Control.Monad.IO.Class import Control.Monad.Trans.Class import Data.Text (Text) import GHC.TypeLits import Network.HTTP.Types.Method import Mig.Core.Types.Http (Request) ------------------------------------------------------------------------------------- -- inputs -- | Generic case for request body. The type encodes a media type and value of the request body. newtype Body media a = Body a {-| Required URL parameter query. > "api/route?foo=bar" ==> (Query bar) :: Query "foo" a -} newtype Query (sym :: Symbol) a = Query a {-| Optional URL parameter query. > "api/route?foo=bar" ==> (Optional maybeBar) :: Query "foo" a -} newtype Optional (sym :: Symbol) a = Optional (Maybe a) {-| Query flag. It is a boolean value in the URL-query. If it is missing it is @False@ if it is in the query but does not have any value it is @True@. Also it can have values @true/false@ in the query. -} newtype QueryFlag (sym :: Symbol) = QueryFlag Bool {-| Argument of capture from the query. > "api/route/{foo} if api/route/bar passed" ==> (Capture bar) :: Capture "Foo" barType -} newtype Capture (sym :: Symbol) a = Capture a {-| Reads value from the required header by name. For example if the request has header: > "foo": "bar" It reads the value: > (Header bar) :: Header "foo" barType -} newtype Header (sym :: Symbol) a = Header a {-| Reads value from the optional header by name. For example if the request has header: > "foo": "bar" It reads the value: > (OptionalHeader (Just bar)) :: OptionalHeader "foo" barType -} newtype OptionalHeader (sym :: Symbol) a = OptionalHeader (Maybe a) {-| Reads a cookie. It's an optional header with name "Cookie". The cookie is URL-encoded and read with instnace of FromForm class. > data MyCookie = MyCookie > { secret :: Text > , count :: Int > } > deriving (Generic, FromForm) > > > "secret=lolkek&count=101" > > (Cookie (Just (MyCookie { secret = "lolkek", count = 101 }))) :: Cookie MyCookie -} newtype Cookie a = Cookie (Maybe a) {-| Reads current path info. > "api/foo/bar" ==> PathInfo ["foo", "bar"] -} newtype PathInfo = PathInfo [Text] {-| Reads current full-path info with queries. > "api/foo/bar?param=value" ==> FullPathInfo "api/foo/bar?param=value" -} newtype FullPathInfo = FullPathInfo Text -- | Read low-level request. Note that it does not affect the API schema newtype RawRequest = RawRequest Request -- | Reads info on weather the connection is secure (made over SSL). newtype IsSecure = IsSecure Bool ------------------------------------------------------------------------------------- -- outputs {-| Route response type. It encodes the route method in the type and which monad is used and which type the response has. The repsonse value is usually one of two cases: * @Resp media a@ -- for routes which always produce a value * @RespOr media err a@ - for routes that can also produce an error or value. See the class @IsResp@ for more details on response types. -} newtype Send method m a = Send {unSend :: m a} deriving newtype (Functor, Applicative, Monad, MonadIO) instance MonadTrans (Send method) where lift = Send -- | type-level GET-method tag data GET -- | type-level POST-method tag data POST -- | type-level PUT-method tag data PUT -- | type-level DELETE-method tag data DELETE -- | type-level OPTIONS-method tag data OPTIONS -- | type-level HEAD-method tag data HEAD -- | type-level PATCH-method tag data PATCH -- | type-level TRACE-method tag data TRACE -- | Get request type Get m a = Send GET m a -- | Post request type Post m a = Send POST m a -- | Put request type Put m a = Send PUT m a -- | Delete request type Delete m a = Send DELETE m a -- | Options request type Options m a = Send OPTIONS m a -- | Head request type Head m a = Send HEAD m a -- | Path request type Patch m a = Send PATCH m a -- | trace request type Trace m a = Send TRACE m a -- | Converts type-level tag for methods to value class IsMethod a where toMethod :: Method instance IsMethod GET where toMethod = methodGet instance IsMethod POST where toMethod = methodPost instance IsMethod PUT where toMethod = methodPut instance IsMethod DELETE where toMethod = methodDelete instance IsMethod OPTIONS where toMethod = methodOptions instance IsMethod HEAD where toMethod = methodHead instance IsMethod PATCH where toMethod = methodPatch instance IsMethod TRACE where toMethod = methodTrace