module Web.Hyperbole.Effect.Response where

import Data.Text (Text)
import Effectful
import Effectful.Dispatch.Dynamic
import Web.Hyperbole.Effect.Hyperbole (Hyperbole (..))
import Web.Hyperbole.Effect.Server (Response (..), ResponseError (..), TargetViewId (..))
import Web.Hyperbole.HyperView (HyperView (..), ViewId (..), hyperUnsafe)
import Web.View (Url, View)


-- | Respond with the given view, and stop execution
respondEarly :: (Hyperbole :> es, HyperView id es) => id -> View id () -> Eff es ()
respondEarly :: forall (es :: [Effect]) id.
(Hyperbole :> es, HyperView id es) =>
id -> View id () -> Eff es ()
respondEarly id
i View id ()
vw = do
  let vid :: TargetViewId
vid = Text -> TargetViewId
TargetViewId (id -> Text
forall a. ViewId a => a -> Text
toViewId id
i)
  let res :: Response
res = TargetViewId -> View () () -> Response
Response TargetViewId
vid (View () () -> Response) -> View () () -> Response
forall a b. (a -> b) -> a -> b
$ id -> View id () -> View () ()
forall id ctx. ViewId id => id -> View id () -> View ctx ()
hyperUnsafe id
i View id ()
vw
  Hyperbole (Eff es) () -> Eff es ()
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) () -> Eff es ())
-> Hyperbole (Eff es) () -> Eff es ()
forall a b. (a -> b) -> a -> b
$ Response -> Hyperbole (Eff es) ()
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly Response
res


{- | Respond immediately with 404 Not Found

@
findUser :: ('Hyperbole' :> es, Users :> es) => Int -> 'Eff' es User
findUser uid = do
  mu <- send (LoadUser uid)
  maybe notFound pure mu

userPage :: ('Hyperbole' :> es, Users :> es) => 'Eff' es ('Page' '[])
userPage = do
  user <- findUser 100

  -- skipped if user not found
  pure $ userView user
@
-}
notFound :: (Hyperbole :> es) => Eff es a
notFound :: forall (es :: [Effect]) a. (Hyperbole :> es) => Eff es a
notFound = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> Hyperbole (Eff es) a -> Eff es a
forall a b. (a -> b) -> a -> b
$ Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly Response
NotFound


-- | Respond immediately with a parse error
parseError :: (Hyperbole :> es) => Text -> Eff es a
parseError :: forall (es :: [Effect]) a. (Hyperbole :> es) => Text -> Eff es a
parseError = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> (Text -> Hyperbole (Eff es) a) -> Text -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly (Response -> Hyperbole (Eff es) a)
-> (Text -> Response) -> Text -> Hyperbole (Eff es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ResponseError -> Response
Err (ResponseError -> Response)
-> (Text -> ResponseError) -> Text -> Response
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ResponseError
ErrParse


-- | Redirect immediately to the 'Url'
redirect :: (Hyperbole :> es) => Url -> Eff es a
redirect :: forall (es :: [Effect]) a. (Hyperbole :> es) => Url -> Eff es a
redirect = Hyperbole (Eff es) a -> Eff es a
forall (e :: Effect) (es :: [Effect]) a.
(HasCallStack, DispatchOf e ~ 'Dynamic, e :> es) =>
e (Eff es) a -> Eff es a
send (Hyperbole (Eff es) a -> Eff es a)
-> (Url -> Hyperbole (Eff es) a) -> Url -> Eff es a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Response -> Hyperbole (Eff es) a
forall (a :: * -> *) b. Response -> Hyperbole a b
RespondEarly (Response -> Hyperbole (Eff es) a)
-> (Url -> Response) -> Url -> Hyperbole (Eff es) a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Url -> Response
Redirect


-- | Manually set the response to the given view. Normally you would return a 'View' from 'runPage' instead
view :: (Hyperbole :> es) => View () () -> Eff es Response
view :: forall (es :: [Effect]).
(Hyperbole :> es) =>
View () () -> Eff es Response
view View () ()
vw = do
  Response -> Eff es Response
forall a. a -> Eff es a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Response -> Eff es Response) -> Response -> Eff es Response
forall a b. (a -> b) -> a -> b
$ TargetViewId -> View () () -> Response
Response (Text -> TargetViewId
TargetViewId Text
"") View () ()
vw