-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Type Safe Web Routing -- -- This library is a solution for http-based routing and dispatch. Its -- goals are similar to the goals of servant, however, -- trasa relies on very different mechanisms to accomplish those -- goals. All typeclasses in this library are optional. All of the real -- work is accomplished with GADTs, universal quantification, and plain -- old haskell data types. @package trasa @version 0.3 module Trasa.Codec newtype CaptureEncoding a CaptureEncoding :: (a -> Text) -> CaptureEncoding a [appCaptureEncoding] :: CaptureEncoding a -> a -> Text class HasCaptureEncoding capStrategy captureEncoding :: HasCaptureEncoding capStrategy => capStrategy a -> CaptureEncoding a newtype CaptureDecoding a CaptureDecoding :: (Text -> Maybe a) -> CaptureDecoding a [appCaptureDecoding] :: CaptureDecoding a -> Text -> Maybe a class HasCaptureDecoding capStrategy captureDecoding :: HasCaptureDecoding capStrategy => capStrategy a -> CaptureDecoding a data CaptureCodec a CaptureCodec :: (a -> Text) -> (Text -> Maybe a) -> CaptureCodec a [captureCodecEncode] :: CaptureCodec a -> a -> Text [captureCodecDecode] :: CaptureCodec a -> Text -> Maybe a class HasCaptureCodec capStrategy captureCodec :: HasCaptureCodec capStrategy => capStrategy a -> CaptureCodec a captureCodecToCaptureEncoding :: CaptureCodec a -> CaptureEncoding a captureCodecToCaptureDecoding :: CaptureCodec a -> CaptureDecoding a data BodyEncoding a BodyEncoding :: NonEmpty MediaType -> (a -> ByteString) -> BodyEncoding a [bodyEncodingNames] :: BodyEncoding a -> NonEmpty MediaType [bodyEncodingFunction] :: BodyEncoding a -> a -> ByteString class HasBodyEncoding bodyStrategy bodyEncoding :: HasBodyEncoding bodyStrategy => bodyStrategy a -> BodyEncoding a data BodyDecoding a BodyDecoding :: NonEmpty MediaType -> (ByteString -> Either Text a) -> BodyDecoding a [bodyDecodingNames] :: BodyDecoding a -> NonEmpty MediaType [bodyDecodingFunction] :: BodyDecoding a -> ByteString -> Either Text a class HasBodyDecoding bodyStrategy bodyDecoding :: HasBodyDecoding bodyStrategy => bodyStrategy a -> BodyDecoding a data BodyCodec a BodyCodec :: NonEmpty MediaType -> (a -> ByteString) -> (ByteString -> Either Text a) -> BodyCodec a [bodyCodecNames] :: BodyCodec a -> NonEmpty MediaType [bodyCodecEncode] :: BodyCodec a -> a -> ByteString [bodyCodecDecode] :: BodyCodec a -> ByteString -> Either Text a class HasBodyCodec bodyStrategy bodyCodec :: HasBodyCodec bodyStrategy => bodyStrategy a -> BodyCodec a bodyCodecToBodyEncoding :: BodyCodec a -> BodyEncoding a bodyCodecToBodyDecoding :: BodyCodec a -> BodyDecoding a showReadCaptureCodec :: (Show a, Read a) => CaptureCodec a showReadBodyCodec :: (Show a, Read a) => BodyCodec a instance Trasa.Codec.HasBodyCodec Trasa.Codec.BodyCodec instance Trasa.Codec.HasBodyEncoding Trasa.Codec.BodyCodec instance Trasa.Codec.HasBodyDecoding Trasa.Codec.BodyCodec instance Trasa.Codec.HasBodyDecoding Trasa.Codec.BodyDecoding instance Trasa.Codec.HasBodyEncoding Trasa.Codec.BodyEncoding instance Trasa.Codec.HasCaptureCodec Trasa.Codec.CaptureCodec instance Trasa.Codec.HasCaptureEncoding Trasa.Codec.CaptureCodec instance Trasa.Codec.HasCaptureDecoding Trasa.Codec.CaptureCodec instance Trasa.Codec.HasCaptureDecoding Trasa.Codec.CaptureDecoding instance Trasa.Codec.HasCaptureEncoding Trasa.Codec.CaptureEncoding module Trasa.Error data TrasaErr TrasaErr :: Status -> ByteString -> TrasaErr [trasaErrStatus] :: TrasaErr -> Status [trasaErrBody] :: TrasaErr -> ByteString status :: Status -> TrasaErr instance GHC.Classes.Ord Trasa.Error.TrasaErr instance GHC.Classes.Eq Trasa.Error.TrasaErr instance GHC.Show.Show Trasa.Error.TrasaErr instance GHC.Exception.Exception Trasa.Error.TrasaErr -- | This module exports symbols that will conflict with the standard -- prelude. It is recommended to be import qualified or just import -- Method and use its IsString instance. module Trasa.Method data Method encodeMethod :: Method -> Text decodeMethod :: Text -> Method get :: Method post :: Method head :: Method put :: Method delete :: Method trace :: Method connect :: Method options :: Method patch :: Method instance GHC.Classes.Ord Trasa.Method.Method instance GHC.Classes.Eq Trasa.Method.Method instance Data.Hashable.Class.Hashable Trasa.Method.Method instance GHC.Show.Show Trasa.Method.Method instance Data.String.IsString Trasa.Method.Method module Trasa.Url data QueryParam QueryParamFlag :: QueryParam QueryParamSingle :: Text -> QueryParam QueryParamList :: [Text] -> QueryParam newtype QueryString QueryString :: HashMap Text QueryParam -> QueryString [unQueryString] :: QueryString -> HashMap Text QueryParam encodeQuery :: QueryString -> Query decodeQuery :: Query -> QueryString data Url Url :: ![Text] -> !QueryString -> Url [urlPath] :: Url -> ![Text] [urlQueryString] :: Url -> !QueryString encodeUrl :: Url -> Text decodeUrl :: Text -> Url instance GHC.Classes.Eq Trasa.Url.Url instance GHC.Classes.Eq Trasa.Url.QueryString instance GHC.Classes.Eq Trasa.Url.QueryParam instance GHC.Show.Show Trasa.Url.Url instance Data.Semigroup.Semigroup Trasa.Url.QueryParam instance GHC.Base.Monoid Trasa.Url.QueryParam module Trasa.Core data Bodiedness Body :: a -> Bodiedness Bodyless :: Bodiedness -- | The HTTP content type and body. data Content Content :: !MediaType -> !ByteString -> Content [contentType] :: Content -> !MediaType [contentData] :: Content -> !ByteString data Payload Payload :: !Url -> !(Maybe Content) -> !(NonEmpty MediaType) -> Payload [payloadUrl] :: Payload -> !Url [payloadContent] :: Payload -> !(Maybe Content) [payloadAccepts] :: Payload -> !(NonEmpty MediaType) data Router route -- | Includes the route, path, query parameters, and request body. data Prepared :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type -> Type [Prepared] :: !(route captures querys request response) -> !(Rec Identity captures) -> !(Rec Parameter querys) -> !(RequestBody Identity request) -> Prepared route response -- | Only needed to implement parseWith. Most users do not need -- this. If you need to create a route hierarchy to provide breadcrumbs, -- then you will need this. data Concealed :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type [Concealed] :: !(route captures querys request response) -> !(Rec Identity captures) -> !(Rec Parameter querys) -> !(RequestBody Identity request) -> Concealed route -- | A route with all types hidden: the captures, the request body, and the -- response body. This is needed so that users can enumerate over all the -- routes. data Constructed :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type [Constructed] :: !(route captures querys request response) -> Constructed route -- | Conceal the response type. conceal :: Prepared route response -> Concealed route concealedToPrepared :: forall route a. Concealed route -> (forall resp. Prepared route resp -> a) -> a mapConstructed :: (forall caps qrys req resp. sub caps qrys req resp -> route caps qrys req resp) -> Constructed sub -> Constructed route data Method encodeMethod :: Method -> Text decodeMethod :: Text -> Method newtype QueryString QueryString :: HashMap Text QueryParam -> QueryString [unQueryString] :: QueryString -> HashMap Text QueryParam encodeQuery :: QueryString -> Query decodeQuery :: Query -> QueryString data Url Url :: ![Text] -> !QueryString -> Url [urlPath] :: Url -> ![Text] [urlQueryString] :: Url -> !QueryString encodeUrl :: Url -> Text decodeUrl :: Text -> Url data TrasaErr TrasaErr :: Status -> ByteString -> TrasaErr [trasaErrStatus] :: TrasaErr -> Status [trasaErrBody] :: TrasaErr -> ByteString status :: Status -> TrasaErr -- | Used my users to define a function called prepare, see tutorial prepareWith :: (forall caps qrys req resp. route caps qrys req resp -> Meta capCodec qryCodec reqCodec respCodec caps qrys req resp) -> route captures query request response -> Arguments captures query request (Prepared route response) -- | Generate a Url for use in hyperlinks. linkWith :: forall route response reqCodec respCodec. (forall caps qrys req resp. route caps qrys req resp -> Meta CaptureEncoding CaptureEncoding reqCodec respCodec caps qrys req resp) -> Prepared route response -> Url -- | Only useful to implement packages like 'trasa-server' dispatchWith :: forall route m. Applicative m => (forall caps qrys req resp. route caps qrys req resp -> MetaServer caps qrys req resp) -> (forall caps qrys req resp. route caps qrys req resp -> Rec Identity caps -> Rec Parameter qrys -> RequestBody Identity req -> m resp) -> Router route -> Method -> [MediaType] -> Url -> Maybe Content -> m (Either TrasaErr Content) -- | Parses the path, the querystring, and the request body. parseWith :: forall route capCodec respCodec. (forall caps qrys req resp. route caps qrys req resp -> Meta capCodec CaptureDecoding (Many BodyDecoding) respCodec caps qrys req resp) -> Router route -> Method -> Url -> Maybe Content -> Either TrasaErr (Concealed route) -- | Only useful for library authors payloadWith :: forall route response. (forall caps qrys req resp. route caps qrys req resp -> MetaClient caps qrys req resp) -> Prepared route response -> Payload requestWith :: Functor m => (forall caps qrys req resp. route caps qrys req resp -> MetaClient caps qrys req resp) -> (Method -> Url -> Maybe Content -> NonEmpty MediaType -> m (Either TrasaErr Content)) -> Prepared route response -> m (Either TrasaErr response) -- | Build a router from all the possible routes, and methods to turn -- routes into needed metadata routerWith :: forall route qryCodec reqCodec respCodec. (forall caps qrys req resp. route caps qrys req resp -> Meta CaptureDecoding qryCodec reqCodec respCodec caps qrys req resp) -> [Constructed route] -> Router route data Path :: (Type -> Type) -> [Type] -> Type [PathNil] :: Path cap '[] [PathConsCapture] :: !(cap a) -> !(Path cap as) -> Path cap (a : as) [PathConsMatch] :: !Text -> !(Path cap as) -> Path cap as match :: Text -> Path cpf caps -> Path cpf caps capture :: cpf cap -> Path cpf caps -> Path cpf (cap : caps) end :: Path cpf '[] (./) :: (a -> b) -> a -> b infixr 7 ./ mapPath :: (forall x. cf x -> cf' x) -> Path cf ps -> Path cf' ps appendPath :: Path f as -> Path f bs -> Path f (as ++ bs) data Param Flag :: Param Optional :: a -> Param List :: a -> Param data Query :: (Type -> Type) -> Param -> Type [QueryFlag] :: !Text -> Query cap Flag [QueryOptional] :: !Text -> !(cap a) -> Query cap (Optional a) [QueryList] :: !Text -> !(cap a) -> Query cap (List a) data Parameter :: Param -> Type [ParameterFlag] :: !Bool -> Parameter Flag [ParameterOptional] :: !(Maybe a) -> Parameter (Optional a) [ParameterList] :: ![a] -> Parameter (List a) -- | A record is parameterized by a universe u, an interpretation -- f and a list of rows rs. The labels or indices of -- the record are given by inhabitants of the kind u; the type -- of values at any label r :: u is given by its interpretation -- f r :: *. data Rec u (a :: u -> *) (b :: [u]) :: forall u. () => (u -> *) -> [u] -> * [RNil] :: Rec u a [] u [:&] :: Rec u a (:) u r rs demoteParameter :: Parameter param -> ParamBase param flag :: Text -> Query cpf Flag optional :: Text -> cpf query -> Query cpf (Optional query) list :: Text -> cpf query -> Query cpf (List query) qend :: Rec (Query qpf) '[] (.&) :: Query qpf q -> Rec (Query qpf) qs -> Rec (Query qpf) (q : qs) infixr 7 .& mapQuery :: (forall x. f x -> g x) -> Rec (Query f) qs -> Rec (Query g) qs data RequestBody :: (Type -> Type) -> Bodiedness -> Type [RequestBodyPresent] :: !(f a) -> RequestBody f ( 'Body a) [RequestBodyAbsent] :: RequestBody f 'Bodyless body :: rqf req -> RequestBody rqf ( 'Body req) bodyless :: RequestBody rqf 'Bodyless encodeRequestBody :: RequestBody (Many BodyEncoding) request -> RequestBody Identity request -> Maybe Content decodeRequestBody :: RequestBody (Many BodyDecoding) req -> Maybe Content -> Either TrasaErr (RequestBody Identity req) mapRequestBody :: (forall x. rqf x -> rqf' x) -> RequestBody rqf request -> RequestBody rqf' request newtype ResponseBody rpf response ResponseBody :: rpf response -> ResponseBody rpf response [getResponseBody] :: ResponseBody rpf response -> rpf response resp :: rpf resp -> ResponseBody rpf resp encodeResponseBody :: forall response. [MediaType] -> ResponseBody (Many BodyEncoding) response -> response -> Either TrasaErr Content decodeResponseBody :: ResponseBody (Many BodyDecoding) response -> Content -> Either TrasaErr response mapResponseBody :: (forall x. rpf x -> rpf' x) -> ResponseBody rpf request -> ResponseBody rpf' request newtype Many f a Many :: NonEmpty (f a) -> Many f a [getMany] :: Many f a -> NonEmpty (f a) one :: f a -> Many f a mapMany :: (forall x. f x -> g x) -> Many f a -> Many g a data Meta capCodec qryCodec reqCodec respCodec caps qrys req resp Meta :: !(Path capCodec caps) -> !(Rec (Query qryCodec) qrys) -> !(RequestBody reqCodec req) -> !(ResponseBody respCodec resp) -> !Method -> Meta capCodec qryCodec reqCodec respCodec caps qrys req resp [metaPath] :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> !(Path capCodec caps) [metaQuery] :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> !(Rec (Query qryCodec) qrys) [metaRequestBody] :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> !(RequestBody reqCodec req) [metaResponseBody] :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> !(ResponseBody respCodec resp) [metaMethod] :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> !Method type MetaBuilder = Meta CaptureCodec CaptureCodec BodyCodec BodyCodec -- | This function is a more general way to transform MetaBuilder -- into MetaCodec. -- -- It wraps the req and resp codecs in Many. metaBuilderToMetaCodec :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> Meta capCodec qryCodec (Many reqCodec) (Many respCodec) caps qrys req resp type MetaCodec = Meta CaptureCodec CaptureCodec (Many BodyCodec) (Many BodyCodec) type MetaClient = Meta CaptureEncoding CaptureEncoding (Many BodyEncoding) (Many BodyDecoding) metaCodecToMetaClient :: MetaCodec caps qrys req resp -> MetaClient caps qrys req resp type MetaServer = Meta CaptureDecoding CaptureDecoding (Many BodyDecoding) (Many BodyEncoding) metaCodecToMetaServer :: MetaCodec caps qrys req resp -> MetaServer caps qrys req resp mapMetaPath :: (forall x. cf x -> cg x) -> Meta cf qryCodec reqCodec respCodec caps qrys req resp -> Meta cg qryCodec reqCodec respCodec caps qrys req resp mapMetaQuery :: (forall x. qf x -> qg x) -> Meta capCodec qf reqCodec respCodec caps qrys req resp -> Meta capCodec qg reqCodec respCodec caps qrys req resp mapMetaRequestBody :: (forall x. rf x -> rg x) -> Meta capCodec qryCodec rf respCodec caps qrys req resp -> Meta capCodec qryCodec rg respCodec caps qrys req resp mapMetaResponseBody :: (forall x. rf x -> rg x) -> Meta capCodec qryCodec reqCodec rf caps qrys req resp -> Meta capCodec qryCodec reqCodec rg caps qrys req resp mapMeta :: (forall x. capCodec1 x -> capCodec2 x) -> (forall x. qryCodec1 x -> qryCodec2 x) -> (forall x. reqCodec1 x -> reqCodec2 x) -> (forall x. respCodec1 x -> respCodec2 x) -> Meta capCodec1 qryCodec1 reqCodec1 respCodec1 caps qrys req resp -> Meta capCodec2 qryCodec2 reqCodec2 respCodec2 caps qrys req resp newtype CaptureEncoding a CaptureEncoding :: (a -> Text) -> CaptureEncoding a [appCaptureEncoding] :: CaptureEncoding a -> a -> Text class HasCaptureEncoding capStrategy captureEncoding :: HasCaptureEncoding capStrategy => capStrategy a -> CaptureEncoding a newtype CaptureDecoding a CaptureDecoding :: (Text -> Maybe a) -> CaptureDecoding a [appCaptureDecoding] :: CaptureDecoding a -> Text -> Maybe a class HasCaptureDecoding capStrategy captureDecoding :: HasCaptureDecoding capStrategy => capStrategy a -> CaptureDecoding a data CaptureCodec a CaptureCodec :: (a -> Text) -> (Text -> Maybe a) -> CaptureCodec a [captureCodecEncode] :: CaptureCodec a -> a -> Text [captureCodecDecode] :: CaptureCodec a -> Text -> Maybe a class HasCaptureCodec capStrategy captureCodec :: HasCaptureCodec capStrategy => capStrategy a -> CaptureCodec a data BodyEncoding a BodyEncoding :: NonEmpty MediaType -> (a -> ByteString) -> BodyEncoding a [bodyEncodingNames] :: BodyEncoding a -> NonEmpty MediaType [bodyEncodingFunction] :: BodyEncoding a -> a -> ByteString class HasBodyEncoding bodyStrategy bodyEncoding :: HasBodyEncoding bodyStrategy => bodyStrategy a -> BodyEncoding a data BodyDecoding a BodyDecoding :: NonEmpty MediaType -> (ByteString -> Either Text a) -> BodyDecoding a [bodyDecodingNames] :: BodyDecoding a -> NonEmpty MediaType [bodyDecodingFunction] :: BodyDecoding a -> ByteString -> Either Text a class HasBodyDecoding bodyStrategy bodyDecoding :: HasBodyDecoding bodyStrategy => bodyStrategy a -> BodyDecoding a data BodyCodec a BodyCodec :: NonEmpty MediaType -> (a -> ByteString) -> (ByteString -> Either Text a) -> BodyCodec a [bodyCodecNames] :: BodyCodec a -> NonEmpty MediaType [bodyCodecEncode] :: BodyCodec a -> a -> ByteString [bodyCodecDecode] :: BodyCodec a -> ByteString -> Either Text a class HasBodyCodec bodyStrategy bodyCodec :: HasBodyCodec bodyStrategy => bodyStrategy a -> BodyCodec a captureCodecToCaptureEncoding :: CaptureCodec a -> CaptureEncoding a captureCodecToCaptureDecoding :: CaptureCodec a -> CaptureDecoding a bodyCodecToBodyEncoding :: BodyCodec a -> BodyEncoding a bodyCodecToBodyDecoding :: BodyCodec a -> BodyDecoding a showReadCaptureCodec :: (Show a, Read a) => CaptureCodec a showReadBodyCodec :: (Show a, Read a) => BodyCodec a -- | A closed, total type family provided as a convenience to end users. -- Other function is this library take advantage of Arguments to -- allow end users use normal function application. Without this, users -- would need to write out Record and RequestBody values -- by hand, which is tedious. -- --
--   >>> :kind! Arguments '[Int,Bool] '[Flag,Optional Double,List Int] 'Bodyless Double
--   Arguments '[Int,Bool] '[Flag,Optional Double,List Int] 'Bodyless Double :: *
--   = Int -> Bool -> Bool -> Maybe Double -> [Int] -> Double
--   
-- | Uncurry the arguments type family handler :: forall captures querys request x. Rec Identity captures -> Rec Parameter querys -> RequestBody Identity request -> Arguments captures querys request x -> x -- | Pretty prints a router, using indentation to show nesting of routes -- under a common prefix. This also shows the request methods that each -- route accepts. If there are any trivially overlapped routes, the -- appends are asterisk to the method name for which the routes are -- overlapped. prettyRouter :: Router route -> String instance GHC.Classes.Ord Trasa.Core.Content instance GHC.Classes.Eq Trasa.Core.Content instance GHC.Show.Show Trasa.Core.Content instance GHC.Base.Functor f => GHC.Base.Functor (Trasa.Core.Many f) instance GHC.Base.Monoid (Trasa.Core.IxedRouter route n) instance Data.Semigroup.Semigroup (Trasa.Core.IxedRouter route n) instance GHC.Base.Applicative f => GHC.Base.Applicative (Trasa.Core.Many f) -- | Users of this library should a data type representing all possible -- routes available in a web application. It is recommended that this -- type be named Route, but this is not required. module Trasa.Tutorial module Trasa.Core.Implicit class HasMeta route where { type family CaptureStrategy route :: Type -> Type; type family QueryStrategy route :: Type -> Type; type family RequestBodyStrategy route :: Type -> Type; type family ResponseBodyStrategy route :: Type -> Type; type CaptureStrategy route = CaptureCodec; type QueryStrategy route = CaptureCodec; type RequestBodyStrategy route = Many BodyCodec; type ResponseBodyStrategy route = Many BodyCodec; } meta :: HasMeta route => route caps qrys req resp -> Meta (CaptureStrategy route) (QueryStrategy route) (RequestBodyStrategy route) (ResponseBodyStrategy route) caps qrys req resp prepare :: HasMeta route => route captures queries request response -> Arguments captures queries request (Prepared route response) link :: (HasMeta route, HasCaptureEncoding (CaptureStrategy route), HasCaptureEncoding (QueryStrategy route)) => Prepared route response -> Url parse :: (HasMeta route, HasCaptureDecoding (CaptureStrategy route), HasCaptureDecoding (QueryStrategy route), RequestBodyStrategy route ~ Many strat, HasBodyDecoding strat, EnumerableRoute route) => Method -> Url -> Maybe Content -> Either TrasaErr (Concealed route) class EnumerableRoute route enumerateRoutes :: EnumerableRoute route => [Constructed route] router :: (HasMeta route, HasCaptureDecoding (CaptureStrategy route), EnumerableRoute route) => Router route