trasa-0.4: Type Safe Web Routing

Safe HaskellNone
LanguageHaskell2010

Trasa.Core

Contents

Synopsis

Types

data Bodiedness Source #

the type of the HTTP message body (json, text, etc) https://en.wikipedia.org/wiki/HTTP_message_body

Constructors

Body a 
Bodyless 

data Content Source #

The HTTP content type and body.

Constructors

Content 
Instances
Eq Content Source # 
Instance details

Defined in Trasa.Core

Methods

(==) :: Content -> Content -> Bool #

(/=) :: Content -> Content -> Bool #

Ord Content Source # 
Instance details

Defined in Trasa.Core

Show Content Source # 
Instance details

Defined in Trasa.Core

data Router route Source #

Existential

data Prepared :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type -> Type where Source #

Includes the route, path, query parameters, and request body.

Constructors

Prepared :: !(route captures querys request response) -> !(Rec Identity captures) -> !(Rec Parameter querys) -> !(RequestBody Identity request) -> Prepared route response 

data Concealed :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type where Source #

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.

Constructors

Concealed :: !(route captures querys request response) -> !(Rec Identity captures) -> !(Rec Parameter querys) -> !(RequestBody Identity request) -> Concealed route 

data Constructed :: ([Type] -> [Param] -> Bodiedness -> Type -> Type) -> Type where Source #

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.

Constructors

Constructed :: !(route captures querys request response) -> Constructed route 

conceal :: Prepared route response -> Concealed route Source #

Conceal the response type.

concealedToPrepared :: forall route a. Concealed route -> (forall resp. Prepared route resp -> a) -> a Source #

mapConstructed :: (forall caps qrys req resp. sub caps qrys req resp -> route caps qrys req resp) -> Constructed sub -> Constructed route Source #

Request Types

Method

data Method Source #

Instances
Eq Method Source # 
Instance details

Defined in Trasa.Method

Methods

(==) :: Method -> Method -> Bool #

(/=) :: Method -> Method -> Bool #

Ord Method Source # 
Instance details

Defined in Trasa.Method

Show Method Source # 
Instance details

Defined in Trasa.Method

IsString Method Source # 
Instance details

Defined in Trasa.Method

Methods

fromString :: String -> Method #

Hashable Method Source # 
Instance details

Defined in Trasa.Method

Methods

hashWithSalt :: Int -> Method -> Int #

hash :: Method -> Int #

Queries

newtype QueryString Source #

Instances
Eq QueryString Source # 
Instance details

Defined in Trasa.Url

Url

data Url Source #

Constructors

Url 
Instances
Eq Url Source # 
Instance details

Defined in Trasa.Url

Methods

(==) :: Url -> Url -> Bool #

(/=) :: Url -> Url -> Bool #

Show Url Source # 
Instance details

Defined in Trasa.Url

Methods

showsPrec :: Int -> Url -> ShowS #

show :: Url -> String #

showList :: [Url] -> ShowS #

Errors

Using Routes

prepareWith Source #

Arguments

:: (forall caps qrys req resp. route caps qrys req resp -> Meta capCodec qryCodec reqCodec respCodec caps qrys req resp) 
-> route captures query request response

The route to prepare

-> Arguments captures query request (Prepared route response) 

Used my users to define a function called prepare, see tutorial

linkWith Source #

Arguments

:: (forall caps qrys req resp. route caps qrys req resp -> Meta CaptureEncoding CaptureEncoding reqCodec respCodec caps qrys req resp) 
-> Prepared route response

The route to encode

-> Url 

Generate a Url for use in hyperlinks.

dispatchWith Source #

Arguments

:: 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

Router

-> Method

Method

-> [MediaType]

Accept headers

-> Url

Everything after the authority

-> Maybe Content

Content type and request body

-> m (Either TrasaErr Content)

Encoded response

Only useful to implement packages like 'trasa-server'

parseWith Source #

Arguments

:: (forall caps qrys req resp. route caps qrys req resp -> Meta capCodec CaptureDecoding (Many BodyDecoding) respCodec caps qrys req resp) 
-> Router route

Router

-> Method

Request Method

-> Url

Everything after the authority

-> Maybe Content

Request content type and body

-> Either TrasaErr (Concealed route) 

Parses the path, the querystring, and the request body.

payloadWith Source #

Arguments

:: (forall caps qrys req resp. route caps qrys req resp -> MetaClient caps qrys req resp) 
-> Prepared route response

The route to be payload encoded

-> Payload 

Only useful for library authors

requestWith Source #

Arguments

:: 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))

method, url, content, accepts -> response

-> Prepared route response 
-> m (Either TrasaErr response) 

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 Source #

Build a router from all the possible routes, and methods to turn routes into needed metadata

Defining Routes

Path

data Path :: (Type -> Type) -> [Type] -> Type where Source #

Constructors

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 Source #

capture :: cpf cap -> Path cpf caps -> Path cpf (cap ': caps) Source #

end :: Path cpf '[] Source #

(./) :: (a -> b) -> a -> b infixr 7 Source #

flipped ($), useful for constructing routes. e.g. > match "add" . capture int . capture int ./ end

mapPath :: (forall x. cf x -> cf' x) -> Path cf ps -> Path cf' ps Source #

appendPath :: Path f as -> Path f bs -> Path f (as ++ bs) Source #

Query

data Param Source #

Constructors

Flag 
Optional a 
List a 

data Query :: (Type -> Type) -> Param -> Type where Source #

Constructors

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 where Source #

data Rec (a :: k -> Type) (b :: [k]) :: forall k. (k -> Type) -> [k] -> Type where #

Constructors

RecNil :: forall k (a :: k -> Type) (b :: [k]). Rec a ([] :: [k]) 
RecCons :: forall k (a :: k -> Type) (b :: [k]) (r :: k) (rs :: [k]). a r -> Rec a rs -> Rec a (r ': rs) 
Instances
TestCoercion f => TestCoercion (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

testCoercion :: Rec f a -> Rec f b -> Maybe (Coercion a b) #

TestEquality f => TestEquality (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

testEquality :: Rec f a -> Rec f b -> Maybe (a :~: b) #

EqForall f => EqForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

eqForall :: Rec f a -> Rec f a -> Bool #

EqForeach f => EqForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

eqForeach :: Sing a -> Rec f a -> Rec f a -> Bool #

OrdForall f => OrdForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

compareForall :: Rec f a -> Rec f a -> Ordering #

EqForallPoly f => EqForallPoly (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

eqForallPoly :: Rec f a -> Rec f b -> WitnessedEquality a b #

OrdForeach f => OrdForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

compareForeach :: Sing a -> Rec f a -> Rec f a -> Ordering #

ShowForall f => ShowForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

showsPrecForall :: Int -> Rec f a -> ShowS #

ShowForeach f => ShowForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

showsPrecForeach :: Sing a -> Int -> Rec f a -> ShowS #

HashableForall f => HashableForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

hashWithSaltForall :: Int -> Rec f a -> Int #

ToJSONForall f => ToJSONForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

toJSONForall :: Rec f a -> Value #

FromJSONForeach f => FromJSONForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

parseJSONForeach :: Sing a -> Value -> Parser (Rec f a) #

FromJSONExists f => FromJSONExists (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

parseJSONExists :: Value -> Parser (Exists (Rec f)) #

SemigroupForeach f => SemigroupForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

appendForeach :: Sing a -> Rec f a -> Rec f a -> Rec f a #

SemigroupForall f => SemigroupForall (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

appendForall :: Rec f a -> Rec f a -> Rec f a #

StorableForeach f => StorableForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

peekForeach :: Sing a -> Ptr (Rec f a) -> IO (Rec f a) #

pokeForeach :: Sing a -> Ptr (Rec f a) -> Rec f a -> IO () #

sizeOfForeach :: Proxy (Rec f) -> Sing a -> Int #

BinaryForeach f => BinaryForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

putForeach :: Sing a -> Rec f a -> Put #

getForeach :: Sing a -> Get (Rec f a) #

MonoidForeach f => MonoidForeach (Rec f :: [k] -> Type) 
Instance details

Defined in Topaz.Types

Methods

emptyForeach :: Sing a -> Rec f a #

EqForall f => Eq (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

(==) :: Rec f as -> Rec f as -> Bool #

(/=) :: Rec f as -> Rec f as -> Bool #

OrdForall f => Ord (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

compare :: Rec f as -> Rec f as -> Ordering #

(<) :: Rec f as -> Rec f as -> Bool #

(<=) :: Rec f as -> Rec f as -> Bool #

(>) :: Rec f as -> Rec f as -> Bool #

(>=) :: Rec f as -> Rec f as -> Bool #

max :: Rec f as -> Rec f as -> Rec f as #

min :: Rec f as -> Rec f as -> Rec f as #

ShowForall f => Show (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

showsPrec :: Int -> Rec f as -> ShowS #

show :: Rec f as -> String #

showList :: [Rec f as] -> ShowS #

SemigroupForall f => Semigroup (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

(<>) :: Rec f as -> Rec f as -> Rec f as #

sconcat :: NonEmpty (Rec f as) -> Rec f as #

stimes :: Integral b => b -> Rec f as -> Rec f as #

HashableForall f => Hashable (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

hashWithSalt :: Int -> Rec f as -> Int #

hash :: Rec f as -> Int #

ToJSONForall f => ToJSON (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

toJSON :: Rec f as -> Value #

toEncoding :: Rec f as -> Encoding #

toJSONList :: [Rec f as] -> Value #

toEncodingList :: [Rec f as] -> Encoding #

(FromJSONForeach f, Reify as) => FromJSON (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

parseJSON :: Value -> Parser (Rec f as) #

parseJSONList :: Value -> Parser [Rec f as] #

(StorableForeach f, Reify as) => Storable (Rec f as) 
Instance details

Defined in Topaz.Types

Methods

sizeOf :: Rec f as -> Int #

alignment :: Rec f as -> Int #

peekElemOff :: Ptr (Rec f as) -> Int -> IO (Rec f as) #

pokeElemOff :: Ptr (Rec f as) -> Int -> Rec f as -> IO () #

peekByteOff :: Ptr b -> Int -> IO (Rec f as) #

pokeByteOff :: Ptr b -> Int -> Rec f as -> IO () #

peek :: Ptr (Rec f as) -> IO (Rec f as) #

poke :: Ptr (Rec f as) -> Rec f as -> IO () #

optional :: Text -> cpf query -> Query cpf (Optional query) Source #

list :: Text -> cpf query -> Query cpf (List query) Source #

qend :: Rec (Query qpf) '[] Source #

(.&) :: Query qpf q -> Rec (Query qpf) qs -> Rec (Query qpf) (q ': qs) infixr 7 Source #

mapQuery :: (forall x. f x -> g x) -> Rec (Query f) qs -> Rec (Query g) qs Source #

Request Body

data RequestBody :: (Type -> Type) -> Bodiedness -> Type where Source #

body :: rqf req -> RequestBody rqf (Body req) Source #

mapRequestBody :: (forall x. rqf x -> rqf' x) -> RequestBody rqf request -> RequestBody rqf' request Source #

Response Body

newtype ResponseBody rpf response Source #

Constructors

ResponseBody 

Fields

resp :: rpf resp -> ResponseBody rpf resp Source #

encodeResponseBody :: forall response. [MediaType] -> ResponseBody (Many BodyEncoding) response -> response -> Either TrasaErr Content Source #

mapResponseBody :: (forall x. rpf x -> rpf' x) -> ResponseBody rpf request -> ResponseBody rpf' request Source #

Many

newtype Many f a Source #

Constructors

Many 

Fields

Instances
Functor f => Functor (Many f) Source # 
Instance details

Defined in Trasa.Core

Methods

fmap :: (a -> b) -> Many f a -> Many f b #

(<$) :: a -> Many f b -> Many f a #

Applicative f => Applicative (Many f) Source # 
Instance details

Defined in Trasa.Core

Methods

pure :: a -> Many f a #

(<*>) :: Many f (a -> b) -> Many f a -> Many f b #

liftA2 :: (a -> b -> c) -> Many f a -> Many f b -> Many f c #

(*>) :: Many f a -> Many f b -> Many f b #

(<*) :: Many f a -> Many f b -> Many f a #

one :: f a -> Many f a Source #

mapMany :: (forall x. f x -> g x) -> Many f a -> Many g a Source #

Meta

data Meta capCodec qryCodec reqCodec respCodec caps qrys req resp Source #

Constructors

Meta 

Fields

metaBuilderToMetaCodec :: Meta capCodec qryCodec reqCodec respCodec caps qrys req resp -> Meta capCodec qryCodec (Many reqCodec) (Many respCodec) caps qrys req resp Source #

This function is a more general way to transform MetaBuilder into MetaCodec.

It wraps the req and resp codecs in Many.

metaCodecToMetaClient :: MetaCodec caps qrys req resp -> MetaClient caps qrys req resp Source #

metaCodecToMetaServer :: MetaCodec caps qrys req resp -> MetaServer caps qrys req resp Source #

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 Source #

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 Source #

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 Source #

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 Source #

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 Source #

Codecs

class HasCaptureEncoding capStrategy where Source #

Methods

captureEncoding :: capStrategy a -> CaptureEncoding a Source #

class HasCaptureDecoding capStrategy where Source #

Methods

captureDecoding :: capStrategy a -> CaptureDecoding a Source #

class HasCaptureCodec capStrategy where Source #

Methods

captureCodec :: capStrategy a -> CaptureCodec a Source #

Instances
HasCaptureCodec CaptureCodec Source # 
Instance details

Defined in Trasa.Codec

class HasBodyEncoding bodyStrategy where Source #

Methods

bodyEncoding :: bodyStrategy a -> BodyEncoding a Source #

Instances
HasBodyEncoding BodyCodec Source # 
Instance details

Defined in Trasa.Codec

HasBodyEncoding BodyEncoding Source # 
Instance details

Defined in Trasa.Codec

class HasBodyDecoding bodyStrategy where Source #

Methods

bodyDecoding :: bodyStrategy a -> BodyDecoding a Source #

Instances
HasBodyDecoding BodyCodec Source # 
Instance details

Defined in Trasa.Codec

HasBodyDecoding BodyDecoding Source # 
Instance details

Defined in Trasa.Codec

class HasBodyCodec bodyStrategy where Source #

Methods

bodyCodec :: bodyStrategy a -> BodyCodec a Source #

Instances
HasBodyCodec BodyCodec Source # 
Instance details

Defined in Trasa.Codec

Converting Codecs

Type Class based Codecs

Argument Currying

type family ParamBase (param :: Param) :: Type where ... Source #

Equations

ParamBase Flag = Bool 
ParamBase (Optional a) = Maybe a 
ParamBase (List a) = [a] 

type family Arguments (pieces :: [Type]) (querys :: [Param]) (body :: Bodiedness) (result :: Type) :: Type where ... Source #

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

Equations

Arguments '[] '[] (Body b) r = b -> r 
Arguments '[] '[] Bodyless r = r 
Arguments '[] (q ': qs) r b = ParamBase q -> Arguments '[] qs r b 
Arguments (c ': cs) qs b r = c -> Arguments cs qs b r 

handler :: forall captures querys request x. Rec Identity captures -> Rec Parameter querys -> RequestBody Identity request -> Arguments captures querys request x -> x Source #

Uncurry the arguments type family

Helpers

prettyRouter :: Router route -> String Source #

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.