NodeJS¶
The server in Hyper.Node.Server wraps the http module in NodeJS,
and serves middleware using the Aff monad. Here is how you can start
a Node server:
let
  app =
    writeStatus (Tuple 200 "OK")
    :*> closeHeaders
    :*> respond "Hello there!"
in runServer defaultOptions {} app
As seen above, runServer takes a record of options, an initial
components record, and your application middleware. If you want to do
logging on server startup, and on any request handling errors, use
defaultOptionsWithLogging.
Monad Transformers¶
You might want to use a monad transformer stack in your application, for
instance as a way to pass configuration, or to accumulate some state in
the chain of middleware. The underlying monad of Middleware is
parameterized for this exact purpose. When running the NodeJS server
with monad transformers, you need to use runServer' instead of the regular
runServer, and pass a function that runs your monad and returns an Aff
value.
The following code runs a middleware using the ReaderT monad
transformer. Note that the runAppM function might need to be defined
at the top-level to please the type checker.
type MyConfig = { thingToSay :: String }
runAppM
  :: forall e a.
    ReaderT MyConfig (Aff e) a
  -> Aff e a
runAppM = flip runReaderT { thingToSay: "Hello, ReaderT!" }
main :: forall e. Eff (console :: CONSOLE, http :: HTTP | e) Unit
main =
  let app =
        lift' ask :>>= \config ->
          writeStatus statusOK
          :*> closeHeaders
          :*> respond config.thingToSay
  in runServer' defaultOptionsWithLogging {} runAppM app
In a real-world application the configuration type MyConfig could
hold a database connection pool, or settings read from the environment,
for example.
