-- | This executable serves as an example for how to start @hipsql@ from -- your own program, either directly in 'IO' or within your own 'Monad'. {-# LANGUAGE BlockArguments #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# OPTIONS_GHC -fno-warn-orphans #-} module Main where import Control.Exception (bracket) import Control.Monad.IO.Class (MonadIO(liftIO)) import Control.Monad.Reader (MonadReader(ask), ReaderT(runReaderT)) import Data.Maybe (listToMaybe) import GHC.Stack (HasCallStack, SrcLoc, callStack, getCallStack) import Hipsql.Monad (MonadHipsqlAdapter(hipsqlAcquireLibPQ)) import Hipsql.Server (startHipsql) import Hipsql.Server.Adapter (hipsql) import qualified Database.PostgreSQL.LibPQ as LibPQ -- | Uses env vars as described here: -- https://www.postgresql.org/docs/13/libpq-envars.html -- -- e.g. @PGDATABASE=mydb hipsql@ main :: IO () main = withLibPQConnect \conn -> do demoIO conn runReaderT demoReaderT conn withLibPQConnect :: (LibPQ.Connection -> IO ()) -> IO () withLibPQConnect = bracket (LibPQ.connectdb "") LibPQ.finish -- | Example usage of starting hipsql in 'IO'. demoIO :: LibPQ.Connection -> IO () demoIO conn = do putStrLn "hipsql-demo-server: demonstrating IO ..." startHipsql loc conn where loc :: (HasCallStack) => Maybe SrcLoc loc = fmap snd $ listToMaybe $ getCallStack callStack -- | Example usage of starting hipsql with a 'Monad' which has -- an instance for 'MonadHipsqlAdapter'. demoReaderT :: ReaderT LibPQ.Connection IO () demoReaderT = do liftIO $ putStrLn "hipsql-demo-server: demonstrating ReaderT ..." hipsql -- | Example instance for 'MonadHipsqlAdapter'. This is not necessary -- for using @hipsql@; rather, it is simply convenient. instance MonadHipsqlAdapter (ReaderT LibPQ.Connection IO) where hipsqlAcquireLibPQ f = do conn <- ask liftIO $ f conn