hyperbole-0.3.5: Interactive HTML apps using type-safe serverside Haskell
Safe HaskellSafe-Inferred
LanguageGHC2021

Web.Hyperbole.Application

Synopsis

Documentation

websocketsOr :: ConnectionOptions -> ServerApp -> Application -> Application #

Upgrade a websockets ServerApp to a wai Application. Uses the given backup Application to handle Requests that are not WebSocket requests.

websocketsOr opts ws_app backup_app = \req respond ->
    case websocketsApp opts ws_app req of
        Nothing  -> backup_app req send_response
        Just res -> respond res

For example, below is an Application that sends "Hello, client!" to each connected client.

app :: Application
app = websocketsOr defaultConnectionOptions wsApp backupApp
  where
    wsApp :: ServerApp
    wsApp pending_conn = do
        conn <- acceptRequest pending_conn
        sendTextData conn ("Hello, client!" :: Text)

    backupApp :: Application
    backupApp _ respond = respond $ responseLBS status400 [] "Not a WebSocket request"

defaultConnectionOptions :: ConnectionOptions #

The default connection options:

  • Nothing happens when a pong is received.
  • Compression is disabled.
  • Lenient unicode decoding.
  • 30 second timeout for connection establishment.

liveApp :: (ByteString -> ByteString) -> Eff '[Hyperbole, Server, IOE] Response -> Application Source #

Turn one or more Pages into a Wai Application. Respond using both HTTP and WebSockets

main = do
  run 3000 $ do
  liveApp (basicDocument "Example") $ do
     page mainPage

basicDocument :: Text -> ByteString -> ByteString Source #

wrap HTML fragments in a simple document with a custom title and include required embeds

liveApp (basicDocument "App Title") (routeRequest router)

You may want to specify a custom document function instead:

myDocument :: ByteString -> ByteString
myDocument content =
  [i|<html>
    <head>
      <title>#{title}</title>
      <script type="text/javascript">#{scriptEmbed}</script>
      <style type type="text/css">#{cssResetEmbed}</style>
    </head>
    <body>#{content}</body>
  </html>|]

routeRequest :: (Hyperbole :> es, Route route) => (route -> Eff es Response) -> Eff es Response Source #

Route URL patterns to different pages

import Page.Messages qualified as Messages
import Page.Users qualified as Users

data AppRoute
  = Main
  | Messages
  | Users UserId
  deriving (Eq, Generic, Route)

router :: (Hyperbole :> es) => AppRoute -> Eff es Response
router Messages = page Messages.page
router (Users uid) = page $ Users.page uid
router Main = do
  view $ do
    el_ "click a link below to visit a page"
    route Messages id "Messages"

main = do
  run 3000 $ do
    liveApp (basicDocument "Example") (routeRequest router)