{-# LANGUAGE AllowAmbiguousTypes, UndecidableInstances, LambdaCase #-}
module IHP.RouterSupport (
CanRoute (..)
, HasPath (..)
, AutoRoute (..)
, runAction
, get
, post
, startPage
, frontControllerToWAIApp
, withPrefix
, FrontController (..)
, defaultRouter
, parseRoute
, catchAll
, mountFrontController
, createAction
, updateAction
, urlTo
, parseUUID
, parseId
, parseIntegerId
, remainingText
, parseText
, webSocketApp
, webSocketAppWithCustomPath
, webSocketAppWithHTTPFallback
, onlyAllowMethods
, getMethod
, routeParam
) where
import qualified Prelude
import ClassyPrelude hiding (index, delete, take)
import qualified IHP.ModelSupport as ModelSupport
import IHP.FrameworkConfig
import IHP.ApplicationContext hiding (frameworkConfig)
import Data.UUID
import Network.HTTP.Types.Method
import IHP.Controller.RequestContext
import Network.Wai
import IHP.ControllerSupport
import Data.Attoparsec.ByteString.Char8 (string, Parser, parseOnly, take, endOfInput, choice, takeTill, takeByteString)
import qualified Data.Attoparsec.ByteString.Char8 as Attoparsec
import GHC.TypeLits
import Data.Data
import qualified Control.Monad.State.Strict as State
import qualified Data.Text as Text
import Network.HTTP.Types.URI
import qualified Data.List as List
import Unsafe.Coerce
import IHP.HaskellSupport hiding (get)
import qualified Data.Typeable as Typeable
import qualified Data.ByteString.Char8 as ByteString
import qualified Data.Char as Char
import Control.Monad.Fail
import Data.String.Conversions (ConvertibleStrings (convertString), cs)
import qualified Text.Blaze.Html5 as Html5
import qualified IHP.ErrorController as ErrorController
import qualified Control.Exception as Exception
import qualified Data.List.Split as List
import qualified Network.URI.Encode as URI
import qualified Data.Text.Encoding as Text
import Data.Dynamic
import IHP.Router.Types
import IHP.WebSocket (WSApp)
import qualified IHP.WebSocket as WS
import GHC.TypeLits as T
import IHP.Controller.Context
import IHP.Controller.Param
import qualified Data.TMap as TMap
import qualified IHP.ApplicationContext as ApplicationContext
import Data.Kind
runAction'
:: forall application controller
. ( Controller controller
, ?applicationContext :: ApplicationContext
, InitControllerContext application
, ?application :: application
, Typeable application
, Typeable controller
)
=> controller -> Application
runAction' :: forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' controller
controller Request
request Response -> IO ResponseReceived
respond = do
let ?modelContext = ApplicationContext -> ModelContext
ApplicationContext.modelContext ?applicationContext::ApplicationContext
ApplicationContext
?applicationContext
RequestContext
requestContext <- ApplicationContext
-> Request
-> (Response -> IO ResponseReceived)
-> IO RequestContext
createRequestContext ?applicationContext::ApplicationContext
ApplicationContext
?applicationContext Request
request Response -> IO ResponseReceived
respond
let ?context = ?context::RequestContext
RequestContext
requestContext
let ?requestContext = ?requestContext::RequestContext
RequestContext
requestContext
Either (IO ResponseReceived) ControllerContext
contextOrErrorResponse <- controller -> IO (Either (IO ResponseReceived) ControllerContext)
forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
?context::RequestContext, InitControllerContext application,
?application::application, Typeable application,
Typeable controller) =>
controller -> IO (Either (IO ResponseReceived) ControllerContext)
newContextForAction controller
controller
case Either (IO ResponseReceived) ControllerContext
contextOrErrorResponse of
Left IO ResponseReceived
res -> IO ResponseReceived
res
Right ControllerContext
context -> let ?context = ?context::ControllerContext
ControllerContext
context in controller -> IO ResponseReceived
forall controller.
(Controller controller, ?context::ControllerContext,
?modelContext::ModelContext,
?applicationContext::ApplicationContext,
?requestContext::RequestContext) =>
controller -> IO ResponseReceived
runAction controller
controller
{-# INLINABLE runAction' #-}
class FrontController application where
controllers
:: (?applicationContext :: ApplicationContext, ?application :: application, ?context :: RequestContext)
=> [Parser Application]
router
:: (?applicationContext :: ApplicationContext, ?application :: application, ?context :: RequestContext)
=> [Parser Application] -> Parser Application
router = [Parser Application] -> Parser Application
forall application.
(?applicationContext::ApplicationContext,
?application::application, ?context::RequestContext,
FrontController application) =>
[Parser Application] -> Parser Application
defaultRouter
{-# INLINABLE router #-}
defaultRouter
:: (?applicationContext :: ApplicationContext, ?application :: application, ?context :: RequestContext, FrontController application)
=> [Parser Application] -> Parser Application
defaultRouter :: forall application.
(?applicationContext::ApplicationContext,
?application::application, ?context::RequestContext,
FrontController application) =>
[Parser Application] -> Parser Application
defaultRouter [Parser Application]
additionalControllers = do
let allControllers :: [Parser Application]
allControllers = [Parser Application]
forall application.
(FrontController application,
?applicationContext::ApplicationContext, ?application::application,
?context::RequestContext) =>
[Parser Application]
controllers [Parser Application]
-> [Parser Application] -> [Parser Application]
forall a. Semigroup a => a -> a -> a
<> [Parser Application]
additionalControllers
Application
applications <- [Parser Application] -> Parser Application
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice ([Parser Application] -> Parser Application)
-> [Parser Application] -> Parser Application
forall a b. (a -> b) -> a -> b
$ (Parser Application -> Parser Application)
-> [Parser Application] -> [Parser Application]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\Parser Application
r -> Parser Application
r Parser Application -> Parser ByteString () -> Parser Application
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString ()
forall t. Chunk t => Parser t ()
endOfInput) [Parser Application]
allControllers
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Application
applications
{-# INLINABLE defaultRouter #-}
class HasPath controller where
pathTo :: controller -> Text
urlTo :: (?context :: context, ConfigProvider context, HasPath action) => action -> Text
urlTo :: forall context action.
(?context::context, ConfigProvider context, HasPath action) =>
action -> Text
urlTo action
action = context
?context::context
?context.frameworkConfig.baseUrl Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> action -> Text
forall controller. HasPath controller => controller -> Text
pathTo action
action
{-# INLINE urlTo #-}
class HasPath controller => CanRoute controller where
parseRoute' :: (?context :: RequestContext) => Parser controller
parseFuncs :: forall d idType. (Data d, Data idType) => (ByteString -> Maybe idType) -> [Maybe ByteString -> Either TypedAutoRouteError d]
parseFuncs :: forall d idType.
(Data d, Data idType) =>
(ByteString -> Maybe idType)
-> [Maybe ByteString -> Either TypedAutoRouteError d]
parseFuncs ByteString -> Maybe idType
parseIdType = [
\case
Just ByteString
queryValue -> case Maybe (d :~: Int)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Int) of
Just d :~: Int
Refl -> String -> Maybe d
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay (ByteString -> String
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue :: String)
Maybe d
-> (Maybe d -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \case
Just d
int -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
int
Maybe d
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left BadType { field :: ByteString
field = ByteString
"", value :: Maybe ByteString
value = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
queryValue, expectedType :: ByteString
expectedType = ByteString
"Int" }
Maybe (d :~: Int)
Nothing -> case Maybe (d :~: Maybe Int)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Int) of
Just d :~: Maybe Int
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right (d -> Either TypedAutoRouteError d)
-> d -> Either TypedAutoRouteError d
forall a b. (a -> b) -> a -> b
$ String -> Maybe Int
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay (ByteString -> String
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue :: String)
Maybe (d :~: Maybe Int)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe ByteString
Nothing -> case Maybe (d :~: Maybe Int)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Int) of
Just d :~: Maybe Int
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
Maybe Int
forall a. Maybe a
Nothing
Maybe (d :~: Maybe Int)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\case
Just ByteString
queryValue -> case Maybe (d :~: Integer)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Integer) of
Just d :~: Integer
Refl -> String -> Maybe d
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay (ByteString -> String
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue :: String)
Maybe d
-> (Maybe d -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \case
Just d
int -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
int
Maybe d
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left BadType { field :: ByteString
field = ByteString
"", value :: Maybe ByteString
value = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
queryValue, expectedType :: ByteString
expectedType = ByteString
"Integer" }
Maybe (d :~: Integer)
Nothing -> case Maybe (d :~: Maybe Integer)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Integer) of
Just d :~: Maybe Integer
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right (d -> Either TypedAutoRouteError d)
-> d -> Either TypedAutoRouteError d
forall a b. (a -> b) -> a -> b
$ String -> Maybe Integer
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay (ByteString -> String
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue :: String)
Maybe (d :~: Maybe Integer)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe ByteString
Nothing -> case Maybe (d :~: Maybe Integer)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Integer) of
Just d :~: Maybe Integer
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
Maybe Integer
forall a. Maybe a
Nothing
Maybe (d :~: Maybe Integer)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\case
Just ByteString
queryValue -> case Maybe (d :~: Text)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Text) of
Just d :~: Text
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right (d -> Either TypedAutoRouteError d)
-> d -> Either TypedAutoRouteError d
forall a b. (a -> b) -> a -> b
$ ByteString -> d
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue
Maybe (d :~: Text)
Nothing -> case Maybe (d :~: Maybe Text)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Text) of
Just d :~: Maybe Text
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right (d -> Either TypedAutoRouteError d)
-> d -> Either TypedAutoRouteError d
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue
Maybe (d :~: Maybe Text)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe ByteString
Nothing -> case Maybe (d :~: Maybe Text)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Text) of
Just d :~: Maybe Text
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
Maybe Text
forall a. Maybe a
Nothing
Maybe (d :~: Maybe Text)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\case
Just ByteString
queryValue -> case ByteString -> Maybe idType
parseIdType ByteString
queryValue of
Just idType
idValue -> case Maybe (d :~: idType)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: idType) of
Just d :~: idType
Refl -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right d
idType
idValue
Maybe (d :~: idType)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe idType
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe ByteString
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe (d :~: [Text])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Text]) of
Just d :~: [Text]
Refl -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> [Text] -> Either TypedAutoRouteError [Text]
forall a b. b -> Either a b
Right ([Text] -> Either TypedAutoRouteError [Text])
-> [Text] -> Either TypedAutoRouteError [Text]
forall a b. (a -> b) -> a -> b
$ HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"," (ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue)
Maybe ByteString
Nothing -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right []
Maybe (d :~: [Text])
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe (d :~: [Int])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Int]) of
Just d :~: [Int]
Refl -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"," (ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue)
[Text] -> ([Text] -> [Maybe Int]) -> [Maybe Int]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Text -> Maybe Int) -> [Text] -> [Maybe Int]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map Text -> Maybe Int
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay
[Maybe Int] -> ([Maybe Int] -> [Int]) -> [Int]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Maybe Int] -> [Int]
forall (f :: * -> *) t.
(IsSequence (f (Maybe t)), Functor f,
Element (f (Maybe t)) ~ Maybe t) =>
f (Maybe t) -> f t
catMaybes
[Int]
-> ([Int] -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Int] -> Either TypedAutoRouteError d
[Int] -> Either TypedAutoRouteError [Int]
forall a b. b -> Either a b
Right
Maybe ByteString
Nothing -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right []
Maybe (d :~: [Int])
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe (d :~: [Integer])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Integer]) of
Just d :~: [Integer]
Refl -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
"," (ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryValue)
[Text] -> ([Text] -> [Maybe Integer]) -> [Maybe Integer]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Text -> Maybe Integer) -> [Text] -> [Maybe Integer]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map Text -> Maybe Integer
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay
[Maybe Integer] -> ([Maybe Integer] -> [Integer]) -> [Integer]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Maybe Integer] -> [Integer]
forall (f :: * -> *) t.
(IsSequence (f (Maybe t)), Functor f,
Element (f (Maybe t)) ~ Maybe t) =>
f (Maybe t) -> f t
catMaybes
[Integer]
-> ([Integer] -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Integer] -> Either TypedAutoRouteError d
[Integer] -> Either TypedAutoRouteError [Integer]
forall a b. b -> Either a b
Right
Maybe ByteString
Nothing -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right []
Maybe (d :~: [Integer])
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe (d :~: [UUID])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [UUID]) of
Just d :~: [UUID]
Refl -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> ByteString
queryValue
ByteString -> (ByteString -> Text) -> Text
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ByteString -> Text
forall a b. ConvertibleStrings a b => a -> b
cs
Text -> (Text -> [Text]) -> [Text]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> HasCallStack => Text -> Text -> [Text]
Text -> Text -> [Text]
Text.splitOn Text
","
[Text] -> ([Text] -> [Maybe UUID]) -> [Maybe UUID]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Text -> Maybe UUID) -> [Text] -> [Maybe UUID]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (ByteString -> Maybe UUID
fromASCIIBytes (ByteString -> Maybe UUID)
-> (Text -> ByteString) -> Text -> Maybe UUID
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Text -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs)
[Maybe UUID] -> ([Maybe UUID] -> [UUID]) -> [UUID]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [Maybe UUID] -> [UUID]
forall (f :: * -> *) t.
(IsSequence (f (Maybe t)), Functor f,
Element (f (Maybe t)) ~ Maybe t) =>
f (Maybe t) -> f t
catMaybes
[UUID]
-> ([UUID] -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> [UUID] -> Either TypedAutoRouteError d
[UUID] -> Either TypedAutoRouteError [UUID]
forall a b. b -> Either a b
Right
Maybe ByteString
Nothing -> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right []
Maybe (d :~: [UUID])
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe (d :~: UUID)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: UUID) of
Just d :~: UUID
Refl -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> ByteString
queryValue
ByteString -> (ByteString -> Maybe UUID) -> Maybe UUID
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ByteString -> Maybe UUID
fromASCIIBytes
Maybe UUID
-> (Maybe UUID -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \case
Just UUID
uuid -> UUID
uuid UUID
-> (UUID -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> UUID -> Either TypedAutoRouteError d
UUID -> Either TypedAutoRouteError UUID
forall a b. b -> Either a b
Right
Maybe UUID
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left BadType { field :: ByteString
field = ByteString
"", value :: Maybe ByteString
value = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
queryValue, expectedType :: ByteString
expectedType = ByteString
"UUID" }
Maybe ByteString
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
Maybe (d :~: UUID)
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched,
\Maybe ByteString
queryValue -> case Maybe ByteString
queryValue of
Just ByteString
queryValue -> ByteString
queryValue
ByteString -> (ByteString -> Maybe UUID) -> Maybe UUID
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ByteString -> Maybe UUID
fromASCIIBytes
Maybe UUID
-> (Maybe UUID -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \case
Just UUID
uuid -> UUID
uuid UUID -> (UUID -> d) -> d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> UUID -> d
forall a b. a -> b
unsafeCoerce d
-> (d -> Either TypedAutoRouteError d)
-> Either TypedAutoRouteError d
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> d -> Either TypedAutoRouteError d
forall a b. b -> Either a b
Right
Maybe UUID
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left BadType { field :: ByteString
field = ByteString
"", value :: Maybe ByteString
value = ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just ByteString
queryValue, expectedType :: ByteString
expectedType = ByteString
"UUID" }
Maybe ByteString
Nothing -> TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
NotMatched
]
{-# INLINABLE parseFuncs #-}
querySortedByFields :: Query -> Constr -> Query
querySortedByFields :: Query -> Constr -> Query
querySortedByFields Query
query Constr
constructor = Constr -> [String]
constrFields Constr
constructor
[String] -> ([String] -> [ByteString]) -> [ByteString]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (String -> ByteString) -> [String] -> [ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map String -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs
[ByteString] -> ([ByteString] -> Query) -> Query
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (ByteString -> QueryItem) -> [ByteString] -> Query
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\ByteString
field -> (ByteString
field, Maybe (Maybe ByteString) -> Maybe ByteString
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (Maybe (Maybe ByteString) -> Maybe ByteString)
-> Maybe (Maybe ByteString) -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$ ByteString -> Query -> Maybe (Maybe ByteString)
forall a b. Eq a => a -> [(a, b)] -> Maybe b
List.lookup ByteString
field Query
query))
{-# INLINABLE querySortedByFields #-}
applyConstr :: (Data controller, Data idType) => (ByteString -> Maybe idType) -> Constr -> Query -> Either TypedAutoRouteError controller
applyConstr :: forall controller idType.
(Data controller, Data idType) =>
(ByteString -> Maybe idType)
-> Constr -> Query -> Either TypedAutoRouteError controller
applyConstr ByteString -> Maybe idType
parseIdType Constr
constructor Query
query = let
attemptToParseArg :: forall d. (Data d) => (ByteString, Maybe ByteString) -> [Maybe ByteString -> Either TypedAutoRouteError d] -> State.StateT Query (Either TypedAutoRouteError) d
attemptToParseArg :: forall d.
Data d =>
QueryItem
-> [Maybe ByteString -> Either TypedAutoRouteError d]
-> StateT Query (Either TypedAutoRouteError) d
attemptToParseArg queryParam :: QueryItem
queryParam@(ByteString
queryName, Maybe ByteString
queryValue) [] = Either TypedAutoRouteError d
-> StateT Query (Either TypedAutoRouteError) d
forall (m :: * -> *) a. Monad m => m a -> StateT Query m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
State.lift (TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left NoConstructorMatched
{ field :: ByteString
field = ByteString
queryName
, value :: Maybe ByteString
value = Maybe ByteString
queryValue
, expectedType :: ByteString
expectedType = (d -> DataType
forall a. Data a => a -> DataType
dataTypeOf (d
forall a. HasCallStack => a
Prelude.undefined :: d)) DataType -> (DataType -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> DataType -> String
dataTypeName String -> (String -> ByteString) -> ByteString
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> String -> ByteString
forall a b. ConvertibleStrings a b => a -> b
cs
})
attemptToParseArg queryParam :: QueryItem
queryParam@(ByteString
k, Maybe ByteString
v) (Maybe ByteString -> Either TypedAutoRouteError d
parseFunc:[Maybe ByteString -> Either TypedAutoRouteError d]
restFuncs) = case Maybe ByteString -> Either TypedAutoRouteError d
parseFunc Maybe ByteString
v of
Right d
result -> d -> StateT Query (Either TypedAutoRouteError) d
forall a. a -> StateT Query (Either TypedAutoRouteError) a
forall (f :: * -> *) a. Applicative f => a -> f a
pure d
result
Left badType :: TypedAutoRouteError
badType@BadType{} -> Either TypedAutoRouteError d
-> StateT Query (Either TypedAutoRouteError) d
forall (m :: * -> *) a. Monad m => m a -> StateT Query m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
State.lift (TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
badType { field = k })
Left TypedAutoRouteError
_ -> QueryItem
-> [Maybe ByteString -> Either TypedAutoRouteError d]
-> StateT Query (Either TypedAutoRouteError) d
forall d.
Data d =>
QueryItem
-> [Maybe ByteString -> Either TypedAutoRouteError d]
-> StateT Query (Either TypedAutoRouteError) d
attemptToParseArg QueryItem
queryParam [Maybe ByteString -> Either TypedAutoRouteError d]
restFuncs
nextField :: forall d. (Data d) => State.StateT Query (Either TypedAutoRouteError) d
nextField :: forall d. Data d => StateT Query (Either TypedAutoRouteError) d
nextField = do
Query
queryParams <- StateT Query (Either TypedAutoRouteError) Query
forall s (m :: * -> *). MonadState s m => m s
State.get
case Query
queryParams of
[] -> Either TypedAutoRouteError d
-> StateT Query (Either TypedAutoRouteError) d
forall (m :: * -> *) a. Monad m => m a -> StateT Query m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
State.lift (TypedAutoRouteError -> Either TypedAutoRouteError d
forall a b. a -> Either a b
Left TypedAutoRouteError
TooFewArguments)
(p :: QueryItem
p@(ByteString
key, Maybe ByteString
value):Query
rest) -> do
Query -> StateT Query (Either TypedAutoRouteError) ()
forall s (m :: * -> *). MonadState s m => s -> m ()
State.put Query
rest
QueryItem
-> [Maybe ByteString -> Either TypedAutoRouteError d]
-> StateT Query (Either TypedAutoRouteError) d
forall d.
Data d =>
QueryItem
-> [Maybe ByteString -> Either TypedAutoRouteError d]
-> StateT Query (Either TypedAutoRouteError) d
attemptToParseArg QueryItem
p ((ByteString -> Maybe idType)
-> [Maybe ByteString -> Either TypedAutoRouteError d]
forall d idType.
(Data d, Data idType) =>
(ByteString -> Maybe idType)
-> [Maybe ByteString -> Either TypedAutoRouteError d]
parseFuncs ByteString -> Maybe idType
parseIdType)
in case StateT Query (Either TypedAutoRouteError) controller
-> Query -> Either TypedAutoRouteError (controller, Query)
forall s (m :: * -> *) a. StateT s m a -> s -> m (a, s)
State.runStateT ((forall d. Data d => StateT Query (Either TypedAutoRouteError) d)
-> Constr -> StateT Query (Either TypedAutoRouteError) controller
forall (m :: * -> *) a.
(Monad m, Data a) =>
(forall d. Data d => m d) -> Constr -> m a
fromConstrM StateT Query (Either TypedAutoRouteError) d
forall d. Data d => StateT Query (Either TypedAutoRouteError) d
nextField Constr
constructor) (Query -> Constr -> Query
querySortedByFields Query
query Constr
constructor) of
Right (controller
x, []) -> controller -> Either TypedAutoRouteError controller
forall a. a -> Either TypedAutoRouteError a
forall (f :: * -> *) a. Applicative f => a -> f a
pure controller
x
Right ((controller, Query)
_) -> TypedAutoRouteError -> Either TypedAutoRouteError controller
forall a b. a -> Either a b
Left TypedAutoRouteError
TooFewArguments
Left TypedAutoRouteError
e -> TypedAutoRouteError -> Either TypedAutoRouteError controller
forall a b. a -> Either a b
Left TypedAutoRouteError
e
{-# INLINABLE applyConstr #-}
class Data controller => AutoRoute controller where
autoRouteWithIdType :: (?context :: RequestContext, Data idType) => (ByteString -> Maybe idType) -> Parser controller
autoRouteWithIdType ByteString -> Maybe idType
parseIdFunc =
let
allConstructors :: [Constr]
allConstructors :: [Constr]
allConstructors = DataType -> [Constr]
dataTypeConstrs (controller -> DataType
forall a. Data a => a -> DataType
dataTypeOf (controller
forall a. HasCallStack => a
Prelude.undefined :: controller))
query :: Query
query :: Query
query = Request -> Query
queryString ?context::RequestContext
RequestContext
?context.request
paramValues :: [ByteString]
paramValues :: [ByteString]
paramValues = [Maybe ByteString] -> [ByteString]
forall (f :: * -> *) t.
(IsSequence (f (Maybe t)), Functor f,
Element (f (Maybe t)) ~ Maybe t) =>
f (Maybe t) -> f t
catMaybes ([Maybe ByteString] -> [ByteString])
-> [Maybe ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ (QueryItem -> Maybe ByteString) -> Query -> [Maybe ByteString]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map QueryItem -> Maybe ByteString
forall a b. (a, b) -> b
snd Query
query
parseAction :: Constr -> Parser controller
parseAction :: Constr -> Parser controller
parseAction Constr
constr = let
prefix :: ByteString
prefix :: ByteString
prefix = String -> ByteString
ByteString.pack (forall controller. Typeable controller => String
actionPrefix @controller)
actionName :: ByteString
actionName = String -> ByteString
ByteString.pack (Constr -> String
showConstr Constr
constr)
actionPath :: ByteString
actionPath :: ByteString
actionPath = ByteString -> ByteString
stripActionSuffixByteString ByteString
actionName
allowedMethods :: [StdMethod]
allowedMethods = forall controller.
AutoRoute controller =>
ByteString -> [StdMethod]
allowedMethodsForAction @controller ByteString
actionName
checkRequestMethod :: controller -> Parser controller
checkRequestMethod controller
action = do
StdMethod
method <- Parser StdMethod
(?context::RequestContext) => Parser StdMethod
getMethod
Bool -> Parser ByteString () -> Parser ByteString ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([StdMethod]
allowedMethods [StdMethod] -> ([StdMethod] -> Bool) -> Bool
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Element [StdMethod] -> [StdMethod] -> Bool
forall container.
(MonoFoldable container, Eq (Element container)) =>
Element container -> container -> Bool
includes Element [StdMethod]
StdMethod
method) (UnexpectedMethodException -> Parser ByteString ()
forall a e. Exception e => e -> a
Exception.throw UnexpectedMethodException { [StdMethod]
allowedMethods :: [StdMethod]
allowedMethods :: [StdMethod]
allowedMethods, StdMethod
method :: StdMethod
method :: StdMethod
method })
controller -> Parser controller
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure controller
action
action :: Parser controller
action = case (ByteString -> Maybe idType)
-> Constr -> Query -> Either TypedAutoRouteError controller
forall controller idType.
(Data controller, Data idType) =>
(ByteString -> Maybe idType)
-> Constr -> Query -> Either TypedAutoRouteError controller
applyConstr ByteString -> Maybe idType
parseIdFunc Constr
constr Query
query of
Right controller
parsedAction -> controller -> Parser controller
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure controller
parsedAction
Left TypedAutoRouteError
e -> TypedAutoRouteError -> Parser controller
forall a e. Exception e => e -> a
Exception.throw TypedAutoRouteError
e
in do
controller
parsedAction <- ByteString -> Parser ByteString
string ByteString
prefix Parser ByteString -> Parser controller -> Parser controller
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (ByteString -> Parser ByteString
string ByteString
actionPath Parser ByteString -> Parser ByteString () -> Parser ByteString
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString ()
forall t. Chunk t => Parser t ()
endOfInput) Parser ByteString -> Parser controller -> Parser controller
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser controller
action
controller -> Parser controller
checkRequestMethod controller
parsedAction
in [Parser controller] -> Parser controller
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice ((Constr -> Parser controller) -> [Constr] -> [Parser controller]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map Constr -> Parser controller
parseAction [Constr]
allConstructors)
{-# INLINABLE autoRouteWithIdType #-}
autoRoute :: (?context :: RequestContext) => Parser controller
autoRoute = (ByteString -> Maybe Integer) -> Parser controller
forall idType.
(?context::RequestContext, Data idType) =>
(ByteString -> Maybe idType) -> Parser controller
forall controller idType.
(AutoRoute controller, ?context::RequestContext, Data idType) =>
(ByteString -> Maybe idType) -> Parser controller
autoRouteWithIdType (\ByteString
_ -> Maybe Integer
forall a. Maybe a
Nothing :: Maybe Integer)
{-# INLINABLE autoRoute #-}
allowedMethodsForAction :: ByteString -> [StdMethod]
allowedMethodsForAction ByteString
actionName =
case ByteString
actionName of
ByteString
a | ByteString
"Delete" ByteString -> ByteString -> Bool
`ByteString.isPrefixOf` ByteString
a -> [StdMethod
DELETE]
ByteString
a | ByteString
"Update" ByteString -> ByteString -> Bool
`ByteString.isPrefixOf` ByteString
a -> [StdMethod
POST, StdMethod
PATCH]
ByteString
a | ByteString
"Create" ByteString -> ByteString -> Bool
`ByteString.isPrefixOf` ByteString
a -> [StdMethod
POST]
ByteString
a | ByteString
"Show" ByteString -> ByteString -> Bool
`ByteString.isPrefixOf` ByteString
a -> [StdMethod
GET, StdMethod
HEAD]
ByteString
_ -> [StdMethod
GET, StdMethod
POST, StdMethod
HEAD]
{-# INLINE allowedMethodsForAction #-}
actionPrefix :: forall (controller :: Type). Typeable controller => String
actionPrefix :: forall controller. Typeable controller => String
actionPrefix =
case String
moduleName of
(Char
'W':Char
'e':Char
'b':Char
'.':String
_) -> String
"/"
(Char
'I':Char
'H':Char
'P':Char
'.':String
_) -> String
"/"
(String
"") -> String
"/"
String
moduleName -> String
"/" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> let prefix :: String
prefix = String -> String -> String
getPrefix String
"" String
moduleName in (Char -> Char) -> String -> String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map Char -> Char
Char.toLower String
prefix String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"/"
where
moduleName :: String
moduleName :: String
moduleName = controller -> TypeRep
forall a. Typeable a => a -> TypeRep
Typeable.typeOf (String -> controller
forall a. HasCallStack => String -> a
error String
"unreachable" :: controller)
TypeRep -> (TypeRep -> TyCon) -> TyCon
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> TypeRep -> TyCon
Typeable.typeRepTyCon
TyCon -> (TyCon -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> TyCon -> String
Typeable.tyConModule
getPrefix :: String -> String -> String
getPrefix String
prefix (Char
'.':String
_) = String
prefix
getPrefix String
prefix (Char
x:String
xs) = String -> String -> String
getPrefix (String
prefix String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [Char
x]) String
xs
getPrefix String
prefix [] = String
prefix
{-# INLINE actionPrefix #-}
stripActionSuffixString :: String -> String
stripActionSuffixString :: String -> String
stripActionSuffixString String
string =
case String
string of
String
"Action" -> String
""
(Char
x:String
xs) -> Char
x Char -> String -> String
forall a. a -> [a] -> [a]
: String -> String
stripActionSuffixString String
xs
String
"" -> String
""
{-# INLINE stripActionSuffixString #-}
stripActionSuffixByteString :: ByteString -> ByteString
stripActionSuffixByteString :: ByteString -> ByteString
stripActionSuffixByteString ByteString
actionName = ByteString -> Maybe ByteString -> ByteString
forall a. a -> Maybe a -> a
fromMaybe ByteString
actionName (ByteString -> ByteString -> Maybe ByteString
ByteString.stripSuffix ByteString
"Action" ByteString
actionName)
{-# INLINE stripActionSuffixByteString #-}
createAction :: forall controller. AutoRoute controller => Maybe controller
createAction :: forall controller. AutoRoute controller => Maybe controller
createAction = (Constr -> controller) -> Maybe Constr -> Maybe controller
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Constr -> controller
forall a. Data a => Constr -> a
fromConstr Maybe Constr
createConstructor
where
createConstructor :: Maybe Constr
createConstructor :: Maybe Constr
createConstructor = (Element [Constr] -> Bool) -> [Constr] -> Maybe (Element [Constr])
forall seq.
SemiSequence seq =>
(Element seq -> Bool) -> seq -> Maybe (Element seq)
find Element [Constr] -> Bool
Constr -> Bool
isCreateConstructor [Constr]
allConstructors
allConstructors :: [Constr]
allConstructors :: [Constr]
allConstructors = DataType -> [Constr]
dataTypeConstrs (controller -> DataType
forall a. Data a => a -> DataType
dataTypeOf (controller
forall a. HasCallStack => a
Prelude.undefined :: controller))
isCreateConstructor :: Constr -> Bool
isCreateConstructor :: Constr -> Bool
isCreateConstructor Constr
constructor = String
"Create" String -> String -> Bool
forall seq.
(IsSequence seq, Eq (Element seq)) =>
seq -> seq -> Bool
`isPrefixOf` Constr -> String
showConstr Constr
constructor Bool -> Bool -> Bool
&& [String] -> Bool
forall mono. MonoFoldable mono => mono -> Bool
ClassyPrelude.null (Constr -> [String]
constrFields Constr
constructor)
{-# INLINE createAction #-}
updateAction :: forall controller id. AutoRoute controller => Maybe (id -> controller)
updateAction :: forall controller id.
AutoRoute controller =>
Maybe (id -> controller)
updateAction =
case Maybe Constr
updateConstructor of
Just Constr
constructor -> (id -> controller) -> Maybe (id -> controller)
forall a. a -> Maybe a
Just ((id -> controller) -> Maybe (id -> controller))
-> (id -> controller) -> Maybe (id -> controller)
forall a b. (a -> b) -> a -> b
$ \id
id -> Constr -> id -> controller
buildInstance Constr
constructor id
id
Maybe Constr
Nothing -> Maybe (id -> controller)
forall a. Maybe a
Nothing
where
updateConstructor :: Maybe Constr
updateConstructor :: Maybe Constr
updateConstructor = (Element [Constr] -> Bool) -> [Constr] -> Maybe (Element [Constr])
forall seq.
SemiSequence seq =>
(Element seq -> Bool) -> seq -> Maybe (Element seq)
find Element [Constr] -> Bool
Constr -> Bool
isUpdateConstructor [Constr]
allConstructors
buildInstance :: Constr -> id -> controller
buildInstance :: Constr -> id -> controller
buildInstance Constr
constructor id
id = State Integer controller -> Integer -> controller
forall s a. State s a -> s -> a
State.evalState (((forall d. Data d => StateT Integer Identity d)
-> Constr -> State Integer controller
forall (m :: * -> *) a.
(Monad m, Data a) =>
(forall d. Data d => m d) -> Constr -> m a
fromConstrM (do
Integer
i <- StateT Integer Identity Integer
forall s (m :: * -> *). MonadState s m => m s
State.get
(Integer -> Integer) -> StateT Integer Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
State.modify (Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
+Integer
1)
d -> StateT Integer Identity d
forall a. a -> StateT Integer Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (id -> d
forall a b. a -> b
unsafeCoerce id
id)
)) Constr
constructor) Integer
0
allConstructors :: [Constr]
allConstructors :: [Constr]
allConstructors = DataType -> [Constr]
dataTypeConstrs (controller -> DataType
forall a. Data a => a -> DataType
dataTypeOf (controller
forall a. HasCallStack => a
Prelude.undefined :: controller))
isUpdateConstructor :: Constr -> Bool
isUpdateConstructor :: Constr -> Bool
isUpdateConstructor Constr
constructor = String
"Update" String -> String -> Bool
forall seq.
(IsSequence seq, Eq (Element seq)) =>
seq -> seq -> Bool
`isPrefixOf` (Constr -> String
showConstr Constr
constructor) Bool -> Bool -> Bool
&& ([String] -> Int
forall mono. MonoFoldable mono => mono -> Int
length (Constr -> [String]
constrFields Constr
constructor) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1)
{-# INLINE updateAction #-}
instance {-# OVERLAPPABLE #-} (AutoRoute controller, Controller controller) => CanRoute controller where
parseRoute' :: (?context::RequestContext) => Parser controller
parseRoute' = Parser controller
forall controller.
(AutoRoute controller, ?context::RequestContext) =>
Parser controller
autoRoute
{-# INLINABLE parseRoute' #-}
class Data a => QueryParam a where
showQueryParam :: a -> String
instance QueryParam Text where
showQueryParam :: Text -> String
showQueryParam Text
text = Text -> String
Text.unpack Text
text
instance QueryParam Int where
showQueryParam :: Int -> String
showQueryParam = Int -> String
forall a. Show a => a -> String
show
instance QueryParam Integer where
showQueryParam :: Integer -> String
showQueryParam = Integer -> String
forall a. Show a => a -> String
show
instance QueryParam UUID where
showQueryParam :: UUID -> String
showQueryParam = UUID -> String
forall a. Show a => a -> String
show
instance QueryParam a => QueryParam (Maybe a) where
showQueryParam :: Maybe a -> String
showQueryParam (Just a
val) = a -> String
forall a. QueryParam a => a -> String
showQueryParam a
val
showQueryParam Maybe a
Nothing = String
""
instance QueryParam a => QueryParam [a] where
showQueryParam :: [a] -> String
showQueryParam = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
"," ([String] -> String) -> ([a] -> [String]) -> [a] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (a -> String) -> [a] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map a -> String
forall a. QueryParam a => a -> String
showQueryParam
instance {-# OVERLAPPABLE #-} (Show controller, AutoRoute controller) => HasPath controller where
{-# INLINABLE pathTo #-}
pathTo :: controller -> Text
pathTo !controller
action = String -> Text
Text.pack (String
appPrefix String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
actionName String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
arguments)
where
appPrefix :: String
!appPrefix :: String
appPrefix = forall controller. Typeable controller => String
actionPrefix @controller
actionName :: String
!actionName :: String
actionName = String -> String
stripActionSuffixString (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$! Constr -> String
showConstr Constr
constructor
constructor :: Constr
constructor = controller -> Constr
forall a. Data a => a -> Constr
toConstr controller
action
stripQuotes :: String -> String
stripQuotes (Char
'"':String
rest) = String -> String
forall a. HasCallStack => [a] -> [a]
List.init String
rest
stripQuotes String
otherwise = String
otherwise
showTerms :: controller -> [Maybe String]
showTerms :: controller -> [Maybe String]
showTerms = (forall d. Data d => d -> Maybe String)
-> controller -> [Maybe String]
forall a u. Data a => (forall d. Data d => d -> u) -> a -> [u]
forall u. (forall d. Data d => d -> u) -> controller -> [u]
gmapQ ([d -> Maybe String] -> d -> Maybe String
forall d. Data d => [d -> Maybe String] -> d -> Maybe String
constrShow [d -> Maybe String]
forall d. Data d => [d -> Maybe String]
typeShows)
constrShow :: Data d => [(d -> Maybe String)] -> d -> Maybe String
constrShow :: forall d. Data d => [d -> Maybe String] -> d -> Maybe String
constrShow [] d
_ = Maybe String
forall a. Maybe a
Nothing
constrShow (d -> Maybe String
f:[d -> Maybe String]
fs) d
d = case d -> Maybe String
f d
d of
Just String
str -> String -> Maybe String
forall a. a -> Maybe a
Just String
str
Maybe String
Nothing -> [d -> Maybe String] -> d -> Maybe String
forall d. Data d => [d -> Maybe String] -> d -> Maybe String
constrShow [d -> Maybe String]
fs d
d
typeShows :: forall d. Data d => [(d -> Maybe String)]
typeShows :: forall d. Data d => [d -> Maybe String]
typeShows = [
\d
val -> (Maybe (d :~: Text)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Text))
Maybe (d :~: Text)
-> ((d :~: Text) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Text
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: [Text])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Text]))
Maybe (d :~: [Text])
-> ((d :~: [Text]) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: [Text]
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just ([Text] -> String
forall a. QueryParam a => a -> String
showQueryParam (d
[Text]
val :: [Text])),
\d
val -> (Maybe (d :~: Maybe Text)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Text))
Maybe (d :~: Maybe Text)
-> ((d :~: Maybe Text) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Maybe Text
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: Int)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Int))
Maybe (d :~: Int) -> ((d :~: Int) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Int
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: [Int])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Int]))
Maybe (d :~: [Int])
-> ((d :~: [Int]) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: [Int]
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: Maybe Int)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Int))
Maybe (d :~: Maybe Int)
-> ((d :~: Maybe Int) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Maybe Int
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: Integer)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Integer))
Maybe (d :~: Integer)
-> ((d :~: Integer) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Integer
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: [Integer])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [Integer]))
Maybe (d :~: [Integer])
-> ((d :~: [Integer]) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: [Integer]
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: Maybe Integer)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe Integer))
Maybe (d :~: Maybe Integer)
-> ((d :~: Maybe Integer) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Maybe Integer
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: UUID)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: UUID))
Maybe (d :~: UUID)
-> ((d :~: UUID) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: UUID
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: Maybe UUID)
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: Maybe UUID))
Maybe (d :~: Maybe UUID)
-> ((d :~: Maybe UUID) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: Maybe UUID
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val),
\d
val -> (Maybe (d :~: [UUID])
forall {k} (a :: k) (b :: k).
(Typeable a, Typeable b) =>
Maybe (a :~: b)
eqT :: Maybe (d :~: [UUID]))
Maybe (d :~: [UUID])
-> ((d :~: [UUID]) -> Maybe String) -> Maybe String
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \d :~: [UUID]
Refl -> String -> Maybe String
forall a. a -> Maybe a
Just (d -> String
forall a. QueryParam a => a -> String
showQueryParam d
val)
]
arguments :: String
!arguments :: String
arguments = controller -> String
forall a. Show a => a -> String
show controller
action
String -> (String -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
List.filter (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
' ')
String -> (String -> (String, String)) -> (String, String)
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
List.break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'{')
(String, String) -> ((String, String) -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (String, String) -> String
forall a b. (a, b) -> b
snd
String -> (String -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Int -> String -> String
forall a. Int -> [a] -> [a]
List.drop Int
1
String -> (String -> (String, String)) -> (String, String)
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
List.break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}')
(String, String) -> ((String, String) -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (String, String) -> String
forall a b. (a, b) -> a
fst
String -> (String -> [String]) -> [String]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Char -> Bool) -> String -> [String]
forall a. (a -> Bool) -> [a] -> [[a]]
List.splitWhen (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
',')
[String] -> ([String] -> [(String, String)]) -> [(String, String)]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (String -> (String, String)) -> [String] -> [(String, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\String
s -> let (String
key, String
value) = (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
List.break (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'=') String
s in (String
key, Int -> String -> String
forall a. Int -> [a] -> [a]
List.drop Int
1 String
value))
[(String, String)]
-> ([(String, String)] -> [(String, String)]) -> [(String, String)]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ((String, String) -> (String, String))
-> [(String, String)] -> [(String, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\(String
k ,String
v) -> (String
k, String -> String
stripQuotes String
v))
[(String, String)]
-> ([(String, String)] -> [(String, String)]) -> [(String, String)]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (Element [(String, String)] -> Bool)
-> [(String, String)] -> [(String, String)]
forall seq. IsSequence seq => (Element seq -> Bool) -> seq -> seq
filter (\(String
k, String
v) -> (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null) String
k Bool -> Bool -> Bool
&& (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null) String
v)
[(String, String)] -> ([(String, String)] -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \([(String, String)]
kvs :: [(String, String)]) -> [Maybe String]
-> [(String, String)] -> [(Maybe String, (String, String))]
forall a b. [a] -> [b] -> [(a, b)]
forall (f :: * -> *) a b. Zip f => f a -> f b -> f (a, b)
zip (controller -> [Maybe String]
showTerms controller
action) [(String, String)]
kvs
[(Maybe String, (String, String))]
-> ([(Maybe String, (String, String))] -> [(String, String)])
-> [(String, String)]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ((Maybe String, (String, String)) -> (String, String))
-> [(Maybe String, (String, String))] -> [(String, String)]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\(Maybe String
v1, (String
k, String
v2)) -> (String
k, String -> Maybe String -> String
forall a. a -> Maybe a -> a
fromMaybe String
v2 Maybe String
v1))
[(String, String)] -> ([(String, String)] -> [String]) -> [String]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ((String, String) -> String) -> [(String, String)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\(String
k, String
v) -> if String -> Bool
forall value. IsEmpty value => value -> Bool
isEmpty String
v
then String
""
else String
k String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
"=" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
URI.encode String
v)
[String] -> ([String] -> [String]) -> [String]
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (String -> Bool) -> [String] -> [String]
forall a. (a -> Bool) -> [a] -> [a]
List.filter (Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. String -> Bool
forall value. IsEmpty value => value -> Bool
isEmpty)
[String] -> ([String] -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
"&"
String -> (String -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> (\String
q -> if String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
List.null String
q then String
q else Char
'?'Char -> String -> String
forall a. a -> [a] -> [a]
:String
q)
getMethod :: (?context :: RequestContext) => Parser StdMethod
getMethod :: (?context::RequestContext) => Parser StdMethod
getMethod =
case ByteString -> Either ByteString StdMethod
parseMethod ?context::RequestContext
RequestContext
?context.request.requestMethod of
Left ByteString
error -> String -> Parser StdMethod
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (ByteString -> String
ByteString.unpack ByteString
error)
Right StdMethod
method -> StdMethod -> Parser StdMethod
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure StdMethod
method
{-# INLINABLE getMethod #-}
get :: (Controller action
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable action
) => ByteString -> action -> Parser Application
get :: forall action application.
(Controller action, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application, Typeable action) =>
ByteString -> action -> Parser Application
get ByteString
path action
action = do
StdMethod
method <- Parser StdMethod
(?context::RequestContext) => Parser StdMethod
getMethod
case StdMethod
method of
StdMethod
GET -> do
ByteString -> Parser ByteString
string ByteString
path
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (action -> Application
forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' action
action)
StdMethod
_ -> String -> Parser Application
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid method, expected GET"
{-# INLINABLE get #-}
post :: (Controller action
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable action
) => ByteString -> action -> Parser Application
post :: forall action application.
(Controller action, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application, Typeable action) =>
ByteString -> action -> Parser Application
post ByteString
path action
action = do
StdMethod
method <- Parser StdMethod
(?context::RequestContext) => Parser StdMethod
getMethod
case StdMethod
method of
StdMethod
POST -> do
ByteString -> Parser ByteString
string ByteString
path
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (action -> Application
forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' action
action)
StdMethod
_ -> String -> Parser Application
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Invalid method, expected POST"
{-# INLINABLE post #-}
onlyAllowMethods :: (?context :: RequestContext) => [StdMethod] -> Parser ()
onlyAllowMethods :: (?context::RequestContext) => [StdMethod] -> Parser ByteString ()
onlyAllowMethods [StdMethod]
methods = do
StdMethod
method <- Parser StdMethod
(?context::RequestContext) => Parser StdMethod
getMethod
Bool -> Parser ByteString () -> Parser ByteString ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Element [StdMethod]
StdMethod
method Element [StdMethod] -> [StdMethod] -> Bool
forall container.
(MonoFoldable container, Eq (Element container)) =>
Element container -> container -> Bool
`elem` [StdMethod]
methods) (String -> Parser ByteString ()
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Invalid method, expected one of: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> [StdMethod] -> String
forall a. Show a => a -> String
show [StdMethod]
methods))
{-# INLINABLE onlyAllowMethods #-}
webSocketApp :: forall webSocketApp application.
( WSApp webSocketApp
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable webSocketApp
) => Parser Application
webSocketApp :: forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp) =>
Parser Application
webSocketApp = forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp) =>
ByteString -> Parser Application
webSocketAppWithCustomPath @webSocketApp ByteString
typeName
where
typeName :: ByteString
typeName :: ByteString
typeName = webSocketApp -> TypeRep
forall a. Typeable a => a -> TypeRep
Typeable.typeOf (String -> webSocketApp
forall a. HasCallStack => String -> a
error String
"unreachable" :: webSocketApp)
TypeRep -> (TypeRep -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> TypeRep -> String
forall a. Show a => a -> String
show
String -> (String -> ByteString) -> ByteString
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> String -> ByteString
ByteString.pack
{-# INLINABLE webSocketApp #-}
webSocketAppWithHTTPFallback :: forall webSocketApp application.
( WSApp webSocketApp
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable webSocketApp
, Controller webSocketApp
) => Parser Application
webSocketAppWithHTTPFallback :: forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp, Controller webSocketApp) =>
Parser Application
webSocketAppWithHTTPFallback = forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp, Controller webSocketApp) =>
ByteString -> Parser Application
webSocketAppWithCustomPathAndHTTPFallback @webSocketApp @application ByteString
typeName
where
typeName :: ByteString
typeName :: ByteString
typeName = webSocketApp -> TypeRep
forall a. Typeable a => a -> TypeRep
Typeable.typeOf (String -> webSocketApp
forall a. HasCallStack => String -> a
error String
"unreachable" :: webSocketApp)
TypeRep -> (TypeRep -> String) -> String
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> TypeRep -> String
forall a. Show a => a -> String
show
String -> (String -> ByteString) -> ByteString
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> String -> ByteString
ByteString.pack
{-# INLINABLE webSocketAppWithHTTPFallback #-}
webSocketAppWithCustomPath :: forall webSocketApp application.
( WSApp webSocketApp
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable webSocketApp
) => ByteString -> Parser Application
webSocketAppWithCustomPath :: forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp) =>
ByteString -> Parser Application
webSocketAppWithCustomPath ByteString
path = do
Char -> Parser Char
Attoparsec.char Char
'/'
ByteString -> Parser ByteString
string ByteString
path
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall webSocketApp application.
(?applicationContext::ApplicationContext, ?context::RequestContext,
InitControllerContext application, ?application::application,
Typeable application, WSApp webSocketApp) =>
Application
startWebSocketAppAndFailOnHTTP @webSocketApp)
{-# INLINABLE webSocketAppWithCustomPath #-}
webSocketAppWithCustomPathAndHTTPFallback :: forall webSocketApp application.
( WSApp webSocketApp
, InitControllerContext application
, ?application :: application
, ?applicationContext :: ApplicationContext
, ?context :: RequestContext
, Typeable application
, Typeable webSocketApp
, Controller webSocketApp
) => ByteString -> Parser Application
webSocketAppWithCustomPathAndHTTPFallback :: forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp, Controller webSocketApp) =>
ByteString -> Parser Application
webSocketAppWithCustomPathAndHTTPFallback ByteString
path = do
Char -> Parser Char
Attoparsec.char Char
'/'
ByteString -> Parser ByteString
string ByteString
path
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall webSocketApp application.
(?applicationContext::ApplicationContext, ?context::RequestContext,
InitControllerContext application, ?application::application,
Typeable application, WSApp webSocketApp) =>
IO ResponseReceived -> Application
startWebSocketApp @webSocketApp (webSocketApp -> IO ResponseReceived
forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
?context::RequestContext, InitControllerContext application,
?application::application, Typeable application,
Typeable controller) =>
controller -> IO ResponseReceived
runActionWithNewContext (forall state. WSApp state => state
WS.initialState @webSocketApp)))
{-# INLINABLE webSocketAppWithCustomPathAndHTTPFallback #-}
startPage :: forall action application. (Controller action, InitControllerContext application, ?application::application, ?applicationContext::ApplicationContext, ?context::RequestContext, Typeable application, Typeable action) => action -> Parser Application
startPage :: forall action application.
(Controller action, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application, Typeable action) =>
action -> Parser Application
startPage action
action = ByteString -> action -> Parser Application
forall action application.
(Controller action, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application, Typeable action) =>
ByteString -> action -> Parser Application
get (String -> ByteString
ByteString.pack (forall controller. Typeable controller => String
actionPrefix @action)) action
action
{-# INLINABLE startPage #-}
withPrefix :: ByteString -> [Parser ByteString b] -> Parser ByteString b
withPrefix ByteString
prefix [Parser ByteString b]
routes = ByteString -> Parser ByteString
string ByteString
prefix Parser ByteString -> Parser ByteString b -> Parser ByteString b
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [Parser ByteString b] -> Parser ByteString b
forall (f :: * -> *) a. Alternative f => [f a] -> f a
choice ((Parser ByteString b -> Parser ByteString b)
-> [Parser ByteString b] -> [Parser ByteString b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (\Parser ByteString b
r -> Parser ByteString b
r Parser ByteString b -> Parser ByteString () -> Parser ByteString b
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString ()
forall t. Chunk t => Parser t ()
endOfInput) [Parser ByteString b]
routes)
{-# INLINABLE withPrefix #-}
frontControllerToWAIApp :: forall app (autoRefreshApp :: Type). (?applicationContext :: ApplicationContext, FrontController app, WSApp autoRefreshApp, Typeable autoRefreshApp, InitControllerContext ()) => Middleware -> app -> Application -> Application
frontControllerToWAIApp :: forall app autoRefreshApp.
(?applicationContext::ApplicationContext, FrontController app,
WSApp autoRefreshApp, Typeable autoRefreshApp,
InitControllerContext ()) =>
Middleware -> app -> Middleware
frontControllerToWAIApp Middleware
middleware app
application Application
notFoundAction Request
request Response -> IO ResponseReceived
respond = do
let requestContext :: RequestContext
requestContext = RequestContext { Request
request :: Request
request :: Request
request, Response -> IO ResponseReceived
respond :: Response -> IO ResponseReceived
respond :: Response -> IO ResponseReceived
respond, requestBody :: RequestBody
requestBody = FormBody { params :: [Param]
params = [], files :: [File ByteString]
files = [] }, frameworkConfig :: FrameworkConfig
frameworkConfig = ?applicationContext::ApplicationContext
ApplicationContext
?applicationContext.frameworkConfig }
let ?context = ?context::RequestContext
RequestContext
requestContext
let
path :: ByteString
path = Request
request.rawPathInfo
handleException :: SomeException -> IO (Either String Application)
handleException :: SomeException -> IO (Either String Application)
handleException SomeException
exception = Either String Application -> IO (Either String Application)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Application -> IO (Either String Application))
-> Either String Application -> IO (Either String Application)
forall a b. (a -> b) -> a -> b
$ Application -> Either String Application
forall a b. b -> Either a b
Right (Application -> Either String Application)
-> Application -> Either String Application
forall a b. (a -> b) -> a -> b
$ (?applicationContext::ApplicationContext) =>
SomeException -> Application
SomeException -> Application
ErrorController.handleRouterException SomeException
exception
routes :: Parser Application
routes = let ?application = app
?application::app
application in [Parser Application] -> Parser Application
forall application.
(FrontController application,
?applicationContext::ApplicationContext, ?application::application,
?context::RequestContext) =>
[Parser Application] -> Parser Application
router [let ?application = () in forall webSocketApp application.
(WSApp webSocketApp, InitControllerContext application,
?application::application, ?applicationContext::ApplicationContext,
?context::RequestContext, Typeable application,
Typeable webSocketApp) =>
Parser Application
webSocketApp @autoRefreshApp]
Either String Application
routedAction :: Either String Application <-
(do
Either String Application
res <- Either String Application -> IO (Either String Application)
forall (m :: * -> *) a. MonadIO m => a -> m a
evaluate (Either String Application -> IO (Either String Application))
-> Either String Application -> IO (Either String Application)
forall a b. (a -> b) -> a -> b
$ Parser Application -> ByteString -> Either String Application
forall a. Parser a -> ByteString -> Either String a
parseOnly (Parser Application
routes Parser Application -> Parser ByteString () -> Parser Application
forall a b.
Parser ByteString a -> Parser ByteString b -> Parser ByteString a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser ByteString ()
forall t. Chunk t => Parser t ()
endOfInput) ByteString
path
case Either String Application
res of
Left String
s -> Either String Application -> IO (Either String Application)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Application -> IO (Either String Application))
-> Either String Application -> IO (Either String Application)
forall a b. (a -> b) -> a -> b
$ String -> Either String Application
forall a b. a -> Either a b
Left String
s
Right Application
action -> do
Either String Application -> IO (Either String Application)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Either String Application -> IO (Either String Application))
-> Either String Application -> IO (Either String Application)
forall a b. (a -> b) -> a -> b
$ Application -> Either String Application
forall a b. b -> Either a b
Right Application
action
)
IO (Either String Application)
-> (SomeException -> IO (Either String Application))
-> IO (Either String Application)
forall e a. Exception e => IO a -> (e -> IO a) -> IO a
`Exception.catch` SomeException -> IO (Either String Application)
handleException
case Either String Application
routedAction of
Left String
message -> Application
notFoundAction Request
request Response -> IO ResponseReceived
respond
Right Application
action -> (Middleware
middleware Application
action) Request
request Response -> IO ResponseReceived
respond
{-# INLINABLE frontControllerToWAIApp #-}
mountFrontController :: forall frontController. (?applicationContext :: ApplicationContext, ?context :: RequestContext, FrontController frontController) => frontController -> Parser Application
mountFrontController :: forall frontController.
(?applicationContext::ApplicationContext, ?context::RequestContext,
FrontController frontController) =>
frontController -> Parser Application
mountFrontController frontController
application = let ?application = frontController
?application::frontController
application in [Parser Application] -> Parser Application
forall application.
(FrontController application,
?applicationContext::ApplicationContext, ?application::application,
?context::RequestContext) =>
[Parser Application] -> Parser Application
router []
{-# INLINABLE mountFrontController #-}
parseRoute :: forall controller application. (?applicationContext :: ApplicationContext, ?context :: RequestContext, Controller controller, CanRoute controller, InitControllerContext application, ?application :: application, Typeable application, Typeable controller) => Parser Application
parseRoute :: forall controller application.
(?applicationContext::ApplicationContext, ?context::RequestContext,
Controller controller, CanRoute controller,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
Parser Application
parseRoute = do
controller
action <- forall controller.
(CanRoute controller, ?context::RequestContext) =>
Parser controller
parseRoute' @controller
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Application -> Parser Application)
-> Application -> Parser Application
forall a b. (a -> b) -> a -> b
$ forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' @application controller
action
{-# INLINABLE parseRoute #-}
parseUUIDOrTextId :: ByteString -> Maybe Dynamic
parseUUIDOrTextId :: ByteString -> Maybe Dynamic
parseUUIDOrTextId ByteString
queryVal = ByteString
queryVal
ByteString -> (ByteString -> Maybe UUID) -> Maybe UUID
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> ByteString -> Maybe UUID
fromASCIIBytes
Maybe UUID -> (Maybe UUID -> Maybe Dynamic) -> Maybe Dynamic
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> \case
Just UUID
uuid -> UUID
uuid UUID -> (UUID -> Dynamic) -> Dynamic
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> UUID -> Dynamic
forall a. Typeable a => a -> Dynamic
toDyn Dynamic -> (Dynamic -> Maybe Dynamic) -> Maybe Dynamic
forall {t1} {t2}. t1 -> (t1 -> t2) -> t2
|> Dynamic -> Maybe Dynamic
forall a. a -> Maybe a
Just
Maybe UUID
Nothing -> Maybe Dynamic
forall a. Maybe a
Nothing
parseRouteWithId
:: forall controller application.
(?applicationContext :: ApplicationContext,
?context :: RequestContext,
Controller controller,
CanRoute controller,
InitControllerContext application,
?application :: application,
Typeable application,
Data controller)
=> Parser Application
parseRouteWithId :: forall controller application.
(?applicationContext::ApplicationContext, ?context::RequestContext,
Controller controller, CanRoute controller,
InitControllerContext application, ?application::application,
Typeable application, Data controller) =>
Parser Application
parseRouteWithId = do
controller
action <- forall controller.
(CanRoute controller, ?context::RequestContext) =>
Parser controller
parseRoute' @controller
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' @application controller
action)
catchAll :: forall action application. (?applicationContext :: ApplicationContext, ?context :: RequestContext, Controller action, InitControllerContext application, Typeable action, ?application :: application, Typeable application, Data action) => action -> Parser Application
catchAll :: forall action application.
(?applicationContext::ApplicationContext, ?context::RequestContext,
Controller action, InitControllerContext application,
Typeable action, ?application::application, Typeable application,
Data action) =>
action -> Parser Application
catchAll action
action = do
ByteString -> Parser ByteString
string (String -> ByteString
ByteString.pack (forall controller. Typeable controller => String
actionPrefix @action))
ByteString
_ <- Parser ByteString
takeByteString
Application -> Parser Application
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (forall application controller.
(Controller controller, ?applicationContext::ApplicationContext,
InitControllerContext application, ?application::application,
Typeable application, Typeable controller) =>
controller -> Application
runAction' @application action
action)
{-# INLINABLE catchAll #-}
instance {-# OVERLAPPABLE #-} (HasPath action) => ConvertibleStrings action Html5.AttributeValue where
convertString :: action -> AttributeValue
convertString action
action = Text -> AttributeValue
Html5.textValue (action -> Text
forall controller. HasPath controller => controller -> Text
pathTo action
action)
{-# INLINE convertString #-}
parseUUID :: Parser UUID
parseUUID :: Parser UUID
parseUUID = do
ByteString
uuid <- Int -> Parser ByteString
take Int
36
case ByteString -> Maybe UUID
fromASCIIBytes ByteString
uuid of
Just UUID
theUUID -> UUID -> Parser UUID
forall a. a -> Parser ByteString a
forall (f :: * -> *) a. Applicative f => a -> f a
pure UUID
theUUID
Maybe UUID
Nothing -> String -> Parser UUID
forall a. String -> Parser ByteString a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"not uuid"
{-# INLINABLE parseUUID #-}
parseId :: ((ModelSupport.PrimaryKey table) ~ UUID) => Parser (ModelSupport.Id' table)
parseId :: forall (table :: Symbol).
(PrimaryKey table ~ UUID) =>
Parser (Id' table)
parseId = UUID -> Id' table
PrimaryKey table -> Id' table
forall (table :: Symbol). PrimaryKey table -> Id' table
ModelSupport.Id (UUID -> Id' table) -> Parser UUID -> Parser ByteString (Id' table)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser UUID
parseUUID
{-# INLINABLE parseId #-}
remainingText :: Parser Text
remainingText :: Parser Text
remainingText = ByteString -> Text
Text.decodeUtf8 (ByteString -> Text) -> Parser ByteString -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ByteString
takeByteString
{-# INLINABLE remainingText #-}
parseText :: Parser Text
parseText :: Parser Text
parseText = ByteString -> Text
Text.decodeUtf8 (ByteString -> Text) -> Parser ByteString -> Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> Parser ByteString
takeTill (Char
'/' ==)
{-# INLINABLE parseText #-}
parseIntegerId :: (Data idType) => ByteString -> Maybe idType
parseIntegerId :: forall idType. Data idType => ByteString -> Maybe idType
parseIntegerId ByteString
queryVal = let
Maybe Integer
rawValue :: Maybe Integer = String -> Maybe Integer
forall c a.
(Element c ~ Char, MonoFoldable c, Read a) =>
c -> Maybe a
readMay (ByteString -> String
forall a b. ConvertibleStrings a b => a -> b
cs ByteString
queryVal :: String)
in
Maybe Integer
rawValue Maybe Integer -> (Integer -> Maybe idType) -> Maybe idType
forall a b. Maybe a -> (a -> Maybe b) -> Maybe b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= idType -> Maybe idType
forall a. a -> Maybe a
Just (idType -> Maybe idType)
-> (Integer -> idType) -> Integer -> Maybe idType
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Integer -> idType
forall a b. a -> b
unsafeCoerce
routeParam :: (?context::RequestContext, ParamReader paramType) => ByteString -> paramType
routeParam :: forall paramType.
(?context::RequestContext, ParamReader paramType) =>
ByteString -> paramType
routeParam ByteString
paramName =
let requestContext :: RequestContext
requestContext = ?context::RequestContext
RequestContext
?context
in
let ?context = FrozenControllerContext { requestContext :: RequestContext
requestContext = RequestContext
requestContext, customFields :: TMap
customFields = TMap
forall a. Monoid a => a
mempty }
in ByteString -> paramType
forall valueType.
(?context::ControllerContext, ParamReader valueType) =>
ByteString -> valueType
param ByteString
paramName
instance ((T.TypeError (T.Text "Looks like you forgot to pass a " :<>: (T.ShowType argument) :<>: T.Text " to this " :<>: (T.ShowType controller))), Data argument, Data controller, Data (argument -> controller)) => AutoRoute (argument -> controller) where