{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-} module Trasa.Core.Implicit ( HasMeta(..) , prepare , link , parse , EnumerableRoute(..) , router ) where import Data.Kind (Type) import Trasa.Core class HasMeta route where type CaptureStrategy route :: Type -> Type type CaptureStrategy route = CaptureCodec type QueryStrategy route :: Type -> Type type QueryStrategy route = CaptureCodec type RequestBodyStrategy route :: Type -> Type type RequestBodyStrategy route = Many BodyCodec type ResponseBodyStrategy route :: Type -> Type type ResponseBodyStrategy route = Many BodyCodec meta :: 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) prepare = prepareWith meta link :: (HasMeta route, HasCaptureEncoding (CaptureStrategy route), HasCaptureEncoding (QueryStrategy route)) => Prepared route response -> Url link = linkWith toMeta where toMeta route = m { metaPath = mapPath captureEncoding (metaPath m) , metaQuery = mapQuery captureEncoding (metaQuery m) } where m = meta route parse :: ( HasMeta route , HasCaptureDecoding (CaptureStrategy route) , HasCaptureDecoding (QueryStrategy route) , RequestBodyStrategy route ~ Many strat , HasBodyDecoding strat , EnumerableRoute route ) => Method -- ^ Request Method -> Url -- ^ Everything after the authority -> Maybe Content -- ^ Request content type and body -> Either TrasaErr (Concealed route) parse = parseWith (mapMetaQuery captureDecoding . mapMetaRequestBody (mapMany bodyDecoding) . meta) router class EnumerableRoute route where enumerateRoutes :: [Constructed route] router :: (HasMeta route, HasCaptureDecoding (CaptureStrategy route), EnumerableRoute route) => Router route router = routerWith (mapMetaPath captureDecoding . meta) enumerateRoutes