ema-0.8.0.0: src/Ema/Site.hs
{-# LANGUAGE AllowAmbiguousTypes #-}
module Ema.Site (
EmaSite (..),
EmaStaticSite,
) where
import Control.Monad.Logger (MonadLoggerIO)
import Data.Some (Some)
import Ema.Asset (Asset)
import Ema.CLI qualified as CLI
import Ema.Dynamic (Dynamic)
import Ema.Route.Class (IsRoute (RouteModel))
import Optics.Core (Prism')
import UnliftIO (MonadUnliftIO)
{- | Typeclass to orchestrate an Ema site
Given a route `r` from the class of `IsRoute` types, instantiating EmaSite
on it enables defining the site build pipeline as follows:
@
SiteArg -> siteInput -> Dynamic model --[r, model]--> siteOutput
@
- `SiteArg` is typically not used, but it can be used to pass command line
arguments and other such settings.
- `siteInput` returns a time-varying value (Dynamic) representing the data for
your static site.
- `siteOutput` takes this data model (oneshot value) and returns the generated
content (usually HTML asset, per `SiteOutput`) for the given route.
Finally, `Ema.App.runSite @r arg` (where `arg` is of type `SiteArg`) is run
from the `main` entry point to run your Ema site.
-}
class IsRoute r => EmaSite r where
-- | `SiteArg` is typically settings from the environment (config file, or
-- command-line arguments) that your Dynamic-producing `siteInput` function
-- consumes as argument.
type SiteArg r :: Type
-- By default Ema sites have no site arguments.
type SiteArg r = ()
-- | Type of the value returned by `siteOutput`. Usually `Asset LByteString`
-- but it can be anything.
type SiteOutput r :: Type
type SiteOutput r = Asset LByteString
-- | Get the model's time-varying value as a `Dynamic`.
--
-- If your model is not time-varying, use `pure` to produce a constant value.
siteInput ::
forall m.
(MonadIO m, MonadUnliftIO m, MonadLoggerIO m) =>
Some CLI.Action ->
-- | The value passed by the programmer to `Ema.App.runSite`
SiteArg r ->
-- | Time-varying value of the model. If your model is not time-varying, use
-- `pure` to produce a constant value.
m (Dynamic m (RouteModel r))
-- | Return the output (typically an `Asset`) for the given route and model.
siteOutput ::
forall m.
(MonadIO m, MonadLoggerIO m) =>
Prism' FilePath r ->
RouteModel r ->
r ->
m (SiteOutput r)
-- | Like `EmaSite` but `SiteOutput` is a bytestring `Asset`.
type EmaStaticSite r = (EmaSite r, SiteOutput r ~ Asset LByteString)