-
Notifications
You must be signed in to change notification settings - Fork 26
/
Env.hs
72 lines (60 loc) · 2.1 KB
/
Env.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE TypeSynonymInstances #-}
module Lib.App.Env
( Env (..)
, Has (..)
, grab
-- * Type aliases for 'Env' fields
, DbPool
, Timings
) where
import Colog (HasLog (..), Message)
import Data.Pool (Pool)
import Database.PostgreSQL.Simple (Connection)
import System.Metrics (Store)
import System.Metrics.Distribution (Distribution)
import Lib.Core.Jwt (JwtSecret (..))
import Lib.Core.Session (SessionExpiry, Sessions)
type DbPool = Pool Connection
type Timings = IORef (HashMap Text Distribution)
data Env (m :: Type -> Type) = Env
{ envDbPool :: !DbPool
, envSessions :: !Sessions
, envJwtSecret :: !JwtSecret
, envTimings :: !Timings
, envEkgStore :: !Store
, envSessionExpiry :: !SessionExpiry
, envLogAction :: !(LogAction m Message)
}
instance HasLog (Env m) Message m where
getLogAction :: Env m -> LogAction m Message
getLogAction = envLogAction
{-# INLINE getLogAction #-}
setLogAction :: LogAction m Message -> Env m -> Env m
setLogAction newAction env = env { envLogAction = newAction }
{-# INLINE setLogAction #-}
{- | General type class representing which @field@ is in @env@.
Instead of plain usage like this:
@
foo = do
secret <- asks jwtSecret
@
you should use 'Has' type class like this:
@
foo = do
secret <- grab @JwtSecret
-- secret <- asks $ obtain @JwtSecret
@
-}
class Has field env where
obtain :: env -> field
instance Has DbPool (Env m) where obtain = envDbPool
instance Has Sessions (Env m) where obtain = envSessions
instance Has JwtSecret (Env m) where obtain = envJwtSecret
instance Has Timings (Env m) where obtain = envTimings
instance Has Store (Env m) where obtain = envEkgStore
instance Has SessionExpiry (Env m) where obtain = envSessionExpiry
instance Has (LogAction m Message) (Env m) where obtain = envLogAction
grab :: forall field env m . (MonadReader env m, Has field env) => m field
grab = asks $ obtain @field
{-# INLINE grab #-}