module Ecluse.Core.Server.RouteSpec (
RouteSpec (..),
PathSeg (..),
ParamSpec (..),
specsOf,
) where
import Network.HTTP.Types.Method (StdMethod (GET, HEAD, PUT))
import Ecluse.Core.Server.Contract (RequestSpec, ResponseDoc, bodilessContract, responseDocs)
import Ecluse.Core.Server.Route (
Capture (capDescription, capName),
MethodMatch (MethodPut, MethodRead),
PatternSeg (SegCap, SegLit),
Route (Route, routeContract, routeDescription, routeMethod, routeName, routeRequest, routeSegs, routeSummary),
RouteName (RouteName, unRouteName),
)
data RouteSpec = RouteSpec
{ RouteSpec -> RouteName
rsName :: RouteName
, RouteSpec -> StdMethod
rsMethod :: StdMethod
, RouteSpec -> [PathSeg]
rsPattern :: [PathSeg]
, :: Text
, RouteSpec -> Text
rsDescription :: Text
, RouteSpec -> Maybe RequestSpec
rsRequest :: Maybe RequestSpec
, RouteSpec -> [ResponseDoc]
rsOutcomes :: [ResponseDoc]
}
data PathSeg
= Lit Text
| Param ParamSpec
deriving stock (PathSeg -> PathSeg -> Bool
(PathSeg -> PathSeg -> Bool)
-> (PathSeg -> PathSeg -> Bool) -> Eq PathSeg
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PathSeg -> PathSeg -> Bool
== :: PathSeg -> PathSeg -> Bool
$c/= :: PathSeg -> PathSeg -> Bool
/= :: PathSeg -> PathSeg -> Bool
Eq, Int -> PathSeg -> ShowS
[PathSeg] -> ShowS
PathSeg -> String
(Int -> PathSeg -> ShowS)
-> (PathSeg -> String) -> ([PathSeg] -> ShowS) -> Show PathSeg
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PathSeg -> ShowS
showsPrec :: Int -> PathSeg -> ShowS
$cshow :: PathSeg -> String
show :: PathSeg -> String
$cshowList :: [PathSeg] -> ShowS
showList :: [PathSeg] -> ShowS
Show)
data ParamSpec = ParamSpec
{ ParamSpec -> Text
psName :: Text
, ParamSpec -> Text
psDescription :: Text
}
deriving stock (ParamSpec -> ParamSpec -> Bool
(ParamSpec -> ParamSpec -> Bool)
-> (ParamSpec -> ParamSpec -> Bool) -> Eq ParamSpec
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ParamSpec -> ParamSpec -> Bool
== :: ParamSpec -> ParamSpec -> Bool
$c/= :: ParamSpec -> ParamSpec -> Bool
/= :: ParamSpec -> ParamSpec -> Bool
Eq, Int -> ParamSpec -> ShowS
[ParamSpec] -> ShowS
ParamSpec -> String
(Int -> ParamSpec -> ShowS)
-> (ParamSpec -> String)
-> ([ParamSpec] -> ShowS)
-> Show ParamSpec
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ParamSpec -> ShowS
showsPrec :: Int -> ParamSpec -> ShowS
$cshow :: ParamSpec -> String
show :: ParamSpec -> String
$cshowList :: [ParamSpec] -> ShowS
showList :: [ParamSpec] -> ShowS
Show)
specsOf :: Route v -> [RouteSpec]
specsOf :: forall v. Route v -> [RouteSpec]
specsOf
Route
{ routeName :: forall v. Route v -> RouteName
routeName = RouteName
name
, routeMethod :: forall v. Route v -> MethodMatch
routeMethod = MethodMatch
matchedMethod
, routeSegs :: forall v. Route v -> [PatternSeg v]
routeSegs = [PatternSeg v]
segments
, routeSummary :: forall v. Route v -> Text
routeSummary = Text
summary
, routeDescription :: forall v. Route v -> Text
routeDescription = Text
description
, routeRequest :: forall v. Route v -> Maybe RequestSpec
routeRequest = Maybe RequestSpec
request
, routeContract :: ()
routeContract = ResponseContract response
contract
} = ((StdMethod, RouteName, ResponseContract response) -> RouteSpec)
-> [(StdMethod, RouteName, ResponseContract response)]
-> [RouteSpec]
forall a b. (a -> b) -> [a] -> [b]
map (StdMethod, RouteName, ResponseContract response) -> RouteSpec
forall {response}.
(StdMethod, RouteName, ResponseContract response) -> RouteSpec
operationSpec [(StdMethod, RouteName, ResponseContract response)]
operations
where
operations :: [(StdMethod, RouteName, ResponseContract response)]
operations = case MethodMatch
matchedMethod of
MethodMatch
MethodRead -> [(StdMethod
GET, RouteName
name, ResponseContract response
contract), (StdMethod
HEAD, RouteName -> RouteName
headName RouteName
name, ResponseContract response -> ResponseContract response
forall response.
ResponseContract response -> ResponseContract response
bodilessContract ResponseContract response
contract)]
MethodMatch
MethodPut -> [(StdMethod
PUT, RouteName
name, ResponseContract response
contract)]
operationSpec :: (StdMethod, RouteName, ResponseContract response) -> RouteSpec
operationSpec (StdMethod
method, RouteName
operationName, ResponseContract response
operationContract) =
RouteSpec
{ rsName :: RouteName
rsName = RouteName
operationName
, rsMethod :: StdMethod
rsMethod = StdMethod
method
, rsPattern :: [PathSeg]
rsPattern = (PatternSeg v -> PathSeg) -> [PatternSeg v] -> [PathSeg]
forall a b. (a -> b) -> [a] -> [b]
map PatternSeg v -> PathSeg
forall {v}. PatternSeg v -> PathSeg
paramOf [PatternSeg v]
segments
, rsSummary :: Text
rsSummary = Text
summary
, rsDescription :: Text
rsDescription = Text
description
, rsRequest :: Maybe RequestSpec
rsRequest = Maybe RequestSpec
request
, rsOutcomes :: [ResponseDoc]
rsOutcomes = ResponseContract response -> [ResponseDoc]
forall response. ResponseContract response -> [ResponseDoc]
responseDocs ResponseContract response
operationContract
}
headName :: RouteName -> RouteName
headName RouteName
routeName' = Text -> RouteName
RouteName (RouteName -> Text
unRouteName RouteName
routeName' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".head")
paramOf :: PatternSeg v -> PathSeg
paramOf (SegLit Text
text) = Text -> PathSeg
Lit Text
text
paramOf (SegCap Capture v
capture) = ParamSpec -> PathSeg
Param (Text -> Text -> ParamSpec
ParamSpec (Capture v -> Text
forall v. Capture v -> Text
capName Capture v
capture) (Capture v -> Text
forall v. Capture v -> Text
capDescription Capture v
capture))