hyperbole-0.3.5: example/Main.hs
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# OPTIONS_GHC -Wno-unused-imports #-}
module Main where
import Control.Monad (forever)
import Data.ByteString.Lazy qualified as BL
import Data.String.Conversions (cs)
import Data.String.Interpolate (i)
import Data.Text (Text)
import Data.Text qualified as T
import Data.Text.Lazy qualified as L
import Data.Text.Lazy.Encoding qualified as L
import Effectful
import Effectful.Concurrent.STM
import Effectful.Dispatch.Dynamic
import Effectful.Reader.Static
import Effectful.State.Static.Local
import Example.Contacts qualified as Contacts
import Example.Counter qualified as Counter
import Example.Effects.Debug as Debug
import Example.Effects.Users as Users
import Example.Errors qualified as Errors
import Example.Forms qualified as Forms
import Example.LazyLoading qualified as LazyLoading
import Example.Redirects qualified as Redirects
import Example.Sessions qualified as Sessions
import Example.Simple qualified as Simple
import Example.Style qualified as Style
import Example.Transitions qualified as Transitions
import GHC.Generics (Generic)
import Network.HTTP.Types (Method, QueryItem, methodPost, status200, status404)
import Network.Wai qualified as Wai
import Network.Wai.Handler.Warp qualified as Warp
import Network.Wai.Middleware.Static (addBase, staticPolicy)
import Network.WebSockets (Connection, PendingConnection, acceptRequest, defaultConnectionOptions)
import Web.Hyperbole
import Web.Hyperbole.Effect (Request (..))
-- import Network.Wai.Handler.WebSockets (websocketsOr)
main :: IO ()
main = do
putStrLn "Starting Examples on http://localhost:3000"
users <- initUsers
count <- runEff $ runConcurrent $ newTVarIO 0
Warp.run 3000 $
staticPolicy (addBase "client/dist") $
app users count
data AppRoute
= Main
| Simple
| Hello Hello
| Contacts
| Transitions
| Query
| Counter
| Forms
| Sessions
| Redirects
| RedirectNow
| LazyLoading
| Errors
deriving (Eq, Generic, Route)
data Hello
= Greet Text
| Redirected
deriving (Eq, Generic, Route)
app :: UserStore -> TVar Int -> Application
app users count = do
liveApp
toDocument
(runApp . routeRequest $ router)
where
runApp :: (IOE :> es) => Eff (Concurrent : Debug : Users : es) a -> Eff es a
runApp = runUsersIO users . runDebugIO . runConcurrent
router :: forall es. (Hyperbole :> es, Users :> es, Debug :> es, Concurrent :> es, IOE :> es) => AppRoute -> Eff es Response
router (Hello h) = page $ hello h
router Simple = page Simple.simplePage
router Contacts = page Contacts.page
router Counter = page $ Counter.page count
router Transitions = page Transitions.page
router Forms = page Forms.page
router Sessions = page Sessions.page
router LazyLoading = page LazyLoading.page
router Redirects = page Redirects.page
router Errors = page Errors.page
router RedirectNow = do
redirect (routeUrl $ Hello Redirected)
router Query = do
p <- reqParam "key"
view $ el (pad 20) $ do
text "key: "
text p
router Main = do
view $ do
col (gap 10 . pad 20) $ do
el (bold . fontSize 32) "Examples"
route (Hello (Greet "World")) lnk "Hello World"
route Simple lnk "Simple"
route Counter lnk "Counter"
route Transitions lnk "Transitions"
route Forms lnk "Forms"
link "/query?key=value" lnk "Query Params"
route Sessions lnk "Sessions"
route Redirects lnk "Redirects"
route RedirectNow lnk "Redirect Now"
route LazyLoading lnk "Lazy Loading"
route Contacts lnk "Contacts (Advanced)"
route Errors lnk "Errors"
lnk = Style.link
-- Nested Router
hello :: (Hyperbole :> es, Debug :> es) => Hello -> Page es Response
hello Redirected = load $ do
pure $ el_ "You were redirected"
hello (Greet s) = load $ do
r <- request
pure $ col (gap 10 . pad 10) $ do
el_ $ do
text "Greetings: "
text s
el_ $ do
text "Host: "
text $ cs $ show r.host
el_ $ do
text "Path: "
text $ cs $ show r.path
el_ $ do
text "Query: "
text $ cs $ show r.query
el_ $ do
text "Cookies: "
text $ cs $ show r.cookies
-- Use the embedded version for real applications (see basicDocument).
-- The link to /hyperbole.js here is just to make local development easier
toDocument :: BL.ByteString -> BL.ByteString
toDocument cnt =
[i|<html>
<head>
<title>Hyperbole Examples</title>
<script type="text/javascript" src="/hyperbole.js"></script>
<style type type="text/css">#{cssResetEmbed}</style>
</head>
<body>#{cnt}</body>
</html>|]