{-# LANGUAGE BangPatterns #-}
module LaunchDarkly.Server.Integrations.FileData
( dataSourceFactory
)
where
import Control.Applicative ((<|>))
import Data.Aeson (FromJSON, Value, decode)
import qualified Data.ByteString.Lazy as BSL
import Data.Generics.Product (getField)
import Data.HashSet (HashSet)
import Data.IORef (newIORef, readIORef, writeIORef)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import qualified Data.Yaml as Yaml
import GHC.Generics (Generic)
import GHC.Natural (Natural)
import LaunchDarkly.AesonCompat (KeyMap, mapWithKey)
import LaunchDarkly.Server.Client.Status
import LaunchDarkly.Server.DataSource.Internal (DataSource (..), DataSourceFactory, DataSourceUpdates (..))
import qualified LaunchDarkly.Server.Features as F
data FileFlag = FileFlag
{ FileFlag -> Maybe Natural
version :: Maybe Natural
, FileFlag -> Maybe Bool
on :: Maybe Bool
, FileFlag -> Maybe [Target]
targets :: Maybe [F.Target]
, FileFlag -> Maybe [Target]
contextTargets :: Maybe [F.Target]
, FileFlag -> Maybe [Rule]
rules :: Maybe [F.Rule]
, FileFlag -> Maybe VariationOrRollout
fallthrough :: Maybe F.VariationOrRollout
, FileFlag -> Maybe Integer
offVariation :: Maybe Integer
, FileFlag -> [Value]
variations :: ![Value]
}
deriving ((forall x. FileFlag -> Rep FileFlag x)
-> (forall x. Rep FileFlag x -> FileFlag) -> Generic FileFlag
forall x. Rep FileFlag x -> FileFlag
forall x. FileFlag -> Rep FileFlag x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FileFlag -> Rep FileFlag x
from :: forall x. FileFlag -> Rep FileFlag x
$cto :: forall x. Rep FileFlag x -> FileFlag
to :: forall x. Rep FileFlag x -> FileFlag
Generic, Maybe FileFlag
Value -> Parser [FileFlag]
Value -> Parser FileFlag
(Value -> Parser FileFlag)
-> (Value -> Parser [FileFlag])
-> Maybe FileFlag
-> FromJSON FileFlag
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser FileFlag
parseJSON :: Value -> Parser FileFlag
$cparseJSONList :: Value -> Parser [FileFlag]
parseJSONList :: Value -> Parser [FileFlag]
$comittedField :: Maybe FileFlag
omittedField :: Maybe FileFlag
FromJSON, Int -> FileFlag -> ShowS
[FileFlag] -> ShowS
FileFlag -> String
(Int -> FileFlag -> ShowS)
-> (FileFlag -> String) -> ([FileFlag] -> ShowS) -> Show FileFlag
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileFlag -> ShowS
showsPrec :: Int -> FileFlag -> ShowS
$cshow :: FileFlag -> String
show :: FileFlag -> String
$cshowList :: [FileFlag] -> ShowS
showList :: [FileFlag] -> ShowS
Show, FileFlag -> FileFlag -> Bool
(FileFlag -> FileFlag -> Bool)
-> (FileFlag -> FileFlag -> Bool) -> Eq FileFlag
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileFlag -> FileFlag -> Bool
== :: FileFlag -> FileFlag -> Bool
$c/= :: FileFlag -> FileFlag -> Bool
/= :: FileFlag -> FileFlag -> Bool
Eq)
expandSimpleFlag :: Value -> FileFlag
expandSimpleFlag :: Value -> FileFlag
expandSimpleFlag Value
value =
FileFlag
{ $sel:version:FileFlag :: Maybe Natural
version = Maybe Natural
forall a. Maybe a
Nothing
, $sel:on:FileFlag :: Maybe Bool
on = Maybe Bool
forall a. Maybe a
Nothing
, $sel:targets:FileFlag :: Maybe [Target]
targets = Maybe [Target]
forall a. Maybe a
Nothing
, $sel:contextTargets:FileFlag :: Maybe [Target]
contextTargets = Maybe [Target]
forall a. Maybe a
Nothing
, $sel:rules:FileFlag :: Maybe [Rule]
rules = Maybe [Rule]
forall a. Maybe a
Nothing
, $sel:fallthrough:FileFlag :: Maybe VariationOrRollout
fallthrough = VariationOrRollout -> Maybe VariationOrRollout
forall a. a -> Maybe a
Just (Maybe Integer -> Maybe Rollout -> VariationOrRollout
F.VariationOrRollout (Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
0) Maybe Rollout
forall a. Maybe a
Nothing)
, $sel:offVariation:FileFlag :: Maybe Integer
offVariation = Integer -> Maybe Integer
forall a. a -> Maybe a
Just Integer
0
, $sel:variations:FileFlag :: [Value]
variations = [Value
value]
}
fromFileFlag :: Text -> FileFlag -> F.Flag
fromFileFlag :: Text -> FileFlag -> Flag
fromFileFlag Text
key FileFlag
fileFlag =
F.Flag
{ $sel:key:Flag :: Text
F.key = Text
key
, $sel:version:Flag :: Natural
F.version = Natural -> Maybe Natural -> Natural
forall a. a -> Maybe a -> a
fromMaybe Natural
1 (Maybe Natural -> Natural) -> Maybe Natural -> Natural
forall a b. (a -> b) -> a -> b
$ forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" FileFlag
fileFlag
, $sel:on:Flag :: Bool
F.on = Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
True (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ FileFlag -> Maybe Bool
on FileFlag
fileFlag
, $sel:trackEvents:Flag :: Bool
F.trackEvents = Bool
False
, $sel:trackEventsFallthrough:Flag :: Bool
F.trackEventsFallthrough = Bool
False
, $sel:deleted:Flag :: Bool
F.deleted = Bool
False
, $sel:prerequisites:Flag :: [Prerequisite]
F.prerequisites = []
, $sel:salt:Flag :: Text
F.salt = Text
""
, $sel:targets:Flag :: [Target]
F.targets = [Target] -> Maybe [Target] -> [Target]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Target] -> [Target]) -> Maybe [Target] -> [Target]
forall a b. (a -> b) -> a -> b
$ FileFlag -> Maybe [Target]
targets FileFlag
fileFlag
, $sel:contextTargets:Flag :: [Target]
F.contextTargets = [Target] -> Maybe [Target] -> [Target]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Target] -> [Target]) -> Maybe [Target] -> [Target]
forall a b. (a -> b) -> a -> b
$ FileFlag -> Maybe [Target]
contextTargets FileFlag
fileFlag
, $sel:rules:Flag :: [Rule]
F.rules = [Rule] -> Maybe [Rule] -> [Rule]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [Rule] -> [Rule]) -> Maybe [Rule] -> [Rule]
forall a b. (a -> b) -> a -> b
$ forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"rules" FileFlag
fileFlag
, $sel:fallthrough:Flag :: VariationOrRollout
F.fallthrough = VariationOrRollout
-> Maybe VariationOrRollout -> VariationOrRollout
forall a. a -> Maybe a -> a
fromMaybe VariationOrRollout
noFallthrough (Maybe VariationOrRollout -> VariationOrRollout)
-> Maybe VariationOrRollout -> VariationOrRollout
forall a b. (a -> b) -> a -> b
$ FileFlag -> Maybe VariationOrRollout
fallthrough FileFlag
fileFlag
, $sel:offVariation:Flag :: Maybe Integer
F.offVariation = FileFlag -> Maybe Integer
offVariation FileFlag
fileFlag
, $sel:variations:Flag :: [Value]
F.variations = FileFlag -> [Value]
variations FileFlag
fileFlag
, $sel:debugEventsUntilDate:Flag :: Maybe Natural
F.debugEventsUntilDate = Maybe Natural
forall a. Maybe a
Nothing
, $sel:clientSideAvailability:Flag :: ClientSideAvailability
F.clientSideAvailability = Bool -> Bool -> Bool -> ClientSideAvailability
F.ClientSideAvailability Bool
False Bool
False Bool
False
}
noFallthrough :: F.VariationOrRollout
noFallthrough :: VariationOrRollout
noFallthrough =
Maybe Integer -> Maybe Rollout -> VariationOrRollout
F.VariationOrRollout Maybe Integer
forall a. Maybe a
Nothing Maybe Rollout
forall a. Maybe a
Nothing
data FileSegment = FileSegment
{ FileSegment -> Maybe (HashSet Text)
included :: Maybe (HashSet Text)
, FileSegment -> Maybe [SegmentTarget]
includedContexts :: Maybe [F.SegmentTarget]
, FileSegment -> Maybe (HashSet Text)
excluded :: Maybe (HashSet Text)
, FileSegment -> Maybe [SegmentTarget]
excludedContexts :: Maybe [F.SegmentTarget]
, FileSegment -> Maybe [SegmentRule]
rules :: Maybe [F.SegmentRule]
, FileSegment -> Maybe Natural
version :: Maybe Natural
}
deriving ((forall x. FileSegment -> Rep FileSegment x)
-> (forall x. Rep FileSegment x -> FileSegment)
-> Generic FileSegment
forall x. Rep FileSegment x -> FileSegment
forall x. FileSegment -> Rep FileSegment x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FileSegment -> Rep FileSegment x
from :: forall x. FileSegment -> Rep FileSegment x
$cto :: forall x. Rep FileSegment x -> FileSegment
to :: forall x. Rep FileSegment x -> FileSegment
Generic, Maybe FileSegment
Value -> Parser [FileSegment]
Value -> Parser FileSegment
(Value -> Parser FileSegment)
-> (Value -> Parser [FileSegment])
-> Maybe FileSegment
-> FromJSON FileSegment
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser FileSegment
parseJSON :: Value -> Parser FileSegment
$cparseJSONList :: Value -> Parser [FileSegment]
parseJSONList :: Value -> Parser [FileSegment]
$comittedField :: Maybe FileSegment
omittedField :: Maybe FileSegment
FromJSON, Int -> FileSegment -> ShowS
[FileSegment] -> ShowS
FileSegment -> String
(Int -> FileSegment -> ShowS)
-> (FileSegment -> String)
-> ([FileSegment] -> ShowS)
-> Show FileSegment
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileSegment -> ShowS
showsPrec :: Int -> FileSegment -> ShowS
$cshow :: FileSegment -> String
show :: FileSegment -> String
$cshowList :: [FileSegment] -> ShowS
showList :: [FileSegment] -> ShowS
Show, FileSegment -> FileSegment -> Bool
(FileSegment -> FileSegment -> Bool)
-> (FileSegment -> FileSegment -> Bool) -> Eq FileSegment
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FileSegment -> FileSegment -> Bool
== :: FileSegment -> FileSegment -> Bool
$c/= :: FileSegment -> FileSegment -> Bool
/= :: FileSegment -> FileSegment -> Bool
Eq)
fromFileSegment :: Text -> FileSegment -> F.Segment
fromFileSegment :: Text -> FileSegment -> Segment
fromFileSegment Text
key FileSegment
fileSegment =
F.Segment
{ $sel:key:Segment :: Text
F.key = Text
key
, $sel:version:Segment :: Natural
F.version = Natural -> Maybe Natural -> Natural
forall a. a -> Maybe a -> a
fromMaybe Natural
1 (Maybe Natural -> Natural) -> Maybe Natural -> Natural
forall a b. (a -> b) -> a -> b
$ forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"version" FileSegment
fileSegment
, $sel:included:Segment :: HashSet Text
F.included = HashSet Text -> Maybe (HashSet Text) -> HashSet Text
forall a. a -> Maybe a -> a
fromMaybe HashSet Text
forall a. Monoid a => a
mempty (Maybe (HashSet Text) -> HashSet Text)
-> Maybe (HashSet Text) -> HashSet Text
forall a b. (a -> b) -> a -> b
$ FileSegment -> Maybe (HashSet Text)
included FileSegment
fileSegment
, $sel:includedContexts:Segment :: [SegmentTarget]
F.includedContexts = [SegmentTarget] -> Maybe [SegmentTarget] -> [SegmentTarget]
forall a. a -> Maybe a -> a
fromMaybe [SegmentTarget]
forall a. Monoid a => a
mempty (Maybe [SegmentTarget] -> [SegmentTarget])
-> Maybe [SegmentTarget] -> [SegmentTarget]
forall a b. (a -> b) -> a -> b
$ FileSegment -> Maybe [SegmentTarget]
includedContexts FileSegment
fileSegment
, $sel:excluded:Segment :: HashSet Text
F.excluded = HashSet Text -> Maybe (HashSet Text) -> HashSet Text
forall a. a -> Maybe a -> a
fromMaybe HashSet Text
forall a. Monoid a => a
mempty (Maybe (HashSet Text) -> HashSet Text)
-> Maybe (HashSet Text) -> HashSet Text
forall a b. (a -> b) -> a -> b
$ FileSegment -> Maybe (HashSet Text)
excluded FileSegment
fileSegment
, $sel:excludedContexts:Segment :: [SegmentTarget]
F.excludedContexts = [SegmentTarget] -> Maybe [SegmentTarget] -> [SegmentTarget]
forall a. a -> Maybe a -> a
fromMaybe [SegmentTarget]
forall a. Monoid a => a
mempty (Maybe [SegmentTarget] -> [SegmentTarget])
-> Maybe [SegmentTarget] -> [SegmentTarget]
forall a b. (a -> b) -> a -> b
$ FileSegment -> Maybe [SegmentTarget]
excludedContexts FileSegment
fileSegment
, $sel:salt:Segment :: Text
F.salt = Text
""
, $sel:rules:Segment :: [SegmentRule]
F.rules = [SegmentRule] -> Maybe [SegmentRule] -> [SegmentRule]
forall a. a -> Maybe a -> a
fromMaybe [] (Maybe [SegmentRule] -> [SegmentRule])
-> Maybe [SegmentRule] -> [SegmentRule]
forall a b. (a -> b) -> a -> b
$ forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"rules" FileSegment
fileSegment
, $sel:deleted:Segment :: Bool
F.deleted = Bool
False
}
data FileBody = FileBody
{ FileBody -> Maybe (KeyMap FileFlag)
flags :: Maybe (KeyMap FileFlag)
, FileBody -> Maybe (KeyMap Value)
flagValues :: Maybe (KeyMap Value)
, FileBody -> Maybe (KeyMap FileSegment)
segments :: Maybe (KeyMap FileSegment)
}
deriving ((forall x. FileBody -> Rep FileBody x)
-> (forall x. Rep FileBody x -> FileBody) -> Generic FileBody
forall x. Rep FileBody x -> FileBody
forall x. FileBody -> Rep FileBody x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. FileBody -> Rep FileBody x
from :: forall x. FileBody -> Rep FileBody x
$cto :: forall x. Rep FileBody x -> FileBody
to :: forall x. Rep FileBody x -> FileBody
Generic, Int -> FileBody -> ShowS
[FileBody] -> ShowS
FileBody -> String
(Int -> FileBody -> ShowS)
-> (FileBody -> String) -> ([FileBody] -> ShowS) -> Show FileBody
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> FileBody -> ShowS
showsPrec :: Int -> FileBody -> ShowS
$cshow :: FileBody -> String
show :: FileBody -> String
$cshowList :: [FileBody] -> ShowS
showList :: [FileBody] -> ShowS
Show, Maybe FileBody
Value -> Parser [FileBody]
Value -> Parser FileBody
(Value -> Parser FileBody)
-> (Value -> Parser [FileBody])
-> Maybe FileBody
-> FromJSON FileBody
forall a.
(Value -> Parser a)
-> (Value -> Parser [a]) -> Maybe a -> FromJSON a
$cparseJSON :: Value -> Parser FileBody
parseJSON :: Value -> Parser FileBody
$cparseJSONList :: Value -> Parser [FileBody]
parseJSONList :: Value -> Parser [FileBody]
$comittedField :: Maybe FileBody
omittedField :: Maybe FileBody
FromJSON)
instance Semigroup FileBody where
FileBody
f1 <> :: FileBody -> FileBody -> FileBody
<> FileBody
f2 =
FileBody
{ $sel:flags:FileBody :: Maybe (KeyMap FileFlag)
flags = FileBody -> Maybe (KeyMap FileFlag)
flags FileBody
f1 Maybe (KeyMap FileFlag)
-> Maybe (KeyMap FileFlag) -> Maybe (KeyMap FileFlag)
forall a. Semigroup a => a -> a -> a
<> FileBody -> Maybe (KeyMap FileFlag)
flags FileBody
f2
, $sel:flagValues:FileBody :: Maybe (KeyMap Value)
flagValues = FileBody -> Maybe (KeyMap Value)
flagValues FileBody
f1 Maybe (KeyMap Value)
-> Maybe (KeyMap Value) -> Maybe (KeyMap Value)
forall a. Semigroup a => a -> a -> a
<> FileBody -> Maybe (KeyMap Value)
flagValues FileBody
f2
, $sel:segments:FileBody :: Maybe (KeyMap FileSegment)
segments = FileBody -> Maybe (KeyMap FileSegment)
segments FileBody
f1 Maybe (KeyMap FileSegment)
-> Maybe (KeyMap FileSegment) -> Maybe (KeyMap FileSegment)
forall a. Semigroup a => a -> a -> a
<> FileBody -> Maybe (KeyMap FileSegment)
segments FileBody
f2
}
instance Monoid FileBody where
mempty :: FileBody
mempty =
FileBody
{ $sel:flags:FileBody :: Maybe (KeyMap FileFlag)
flags = Maybe (KeyMap FileFlag)
forall a. Monoid a => a
mempty
, $sel:flagValues:FileBody :: Maybe (KeyMap Value)
flagValues = Maybe (KeyMap Value)
forall a. Monoid a => a
mempty
, $sel:segments:FileBody :: Maybe (KeyMap FileSegment)
segments = Maybe (KeyMap FileSegment)
forall a. Monoid a => a
mempty
}
mappend :: FileBody -> FileBody -> FileBody
mappend = FileBody -> FileBody -> FileBody
forall a. Semigroup a => a -> a -> a
(<>)
dataSourceFactory :: [FilePath] -> DataSourceFactory
dataSourceFactory :: [String] -> DataSourceFactory
dataSourceFactory [String]
sources ClientContext
_clientContext DataSourceUpdates
dataSourceUpdates = do
IORef Bool
inited <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
let dataSourceIsInitialized :: IO Bool
dataSourceIsInitialized =
IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef IORef Bool
inited
dataSourceStart :: IO ()
dataSourceStart = do
FileBody Maybe (KeyMap FileFlag)
mFlags Maybe (KeyMap Value)
mFlagValues Maybe (KeyMap FileSegment)
mSegments <- [FileBody] -> FileBody
forall a. Monoid a => [a] -> a
mconcat ([FileBody] -> FileBody) -> IO [FileBody] -> IO FileBody
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> IO FileBody) -> [String] -> IO [FileBody]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse String -> IO FileBody
loadFile [String]
sources
let mSimpleFlags :: Maybe (KeyMap FileFlag)
mSimpleFlags = (KeyMap Value -> KeyMap FileFlag)
-> Maybe (KeyMap Value) -> Maybe (KeyMap FileFlag)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Value -> FileFlag) -> KeyMap Value -> KeyMap FileFlag
forall a b. (a -> b) -> KeyMap a -> KeyMap b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Value -> FileFlag
expandSimpleFlag) Maybe (KeyMap Value)
mFlagValues
flags' :: KeyMap Flag
flags' = KeyMap Flag
-> (KeyMap FileFlag -> KeyMap Flag)
-> Maybe (KeyMap FileFlag)
-> KeyMap Flag
forall b a. b -> (a -> b) -> Maybe a -> b
maybe KeyMap Flag
forall a. Monoid a => a
mempty ((Text -> FileFlag -> Flag) -> KeyMap FileFlag -> KeyMap Flag
forall v1 v2. (Text -> v1 -> v2) -> KeyMap v1 -> KeyMap v2
mapWithKey Text -> FileFlag -> Flag
fromFileFlag) (Maybe (KeyMap FileFlag)
mFlags Maybe (KeyMap FileFlag)
-> Maybe (KeyMap FileFlag) -> Maybe (KeyMap FileFlag)
forall a. Semigroup a => a -> a -> a
<> Maybe (KeyMap FileFlag)
mSimpleFlags)
segments' :: KeyMap Segment
segments' = KeyMap Segment
-> (KeyMap FileSegment -> KeyMap Segment)
-> Maybe (KeyMap FileSegment)
-> KeyMap Segment
forall b a. b -> (a -> b) -> Maybe a -> b
maybe KeyMap Segment
forall a. Monoid a => a
mempty ((Text -> FileSegment -> Segment)
-> KeyMap FileSegment -> KeyMap Segment
forall v1 v2. (Text -> v1 -> v2) -> KeyMap v1 -> KeyMap v2
mapWithKey Text -> FileSegment -> Segment
fromFileSegment) Maybe (KeyMap FileSegment)
mSegments
Either Text ()
_ <- DataSourceUpdates
-> KeyMap Flag -> KeyMap Segment -> IO (Either Text ())
dataSourceUpdatesInit DataSourceUpdates
dataSourceUpdates KeyMap Flag
flags' KeyMap Segment
segments'
DataSourceUpdates -> Status -> IO ()
dataSourceUpdatesSetStatus DataSourceUpdates
dataSourceUpdates Status
Initialized
IORef Bool -> Bool -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
inited Bool
True
dataSourceStop :: f ()
dataSourceStop = () -> f ()
forall a. a -> f a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
DataSource -> IO DataSource
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DataSource -> IO DataSource) -> DataSource -> IO DataSource
forall a b. (a -> b) -> a -> b
$ DataSource {IO Bool
IO ()
forall {f :: * -> *}. Applicative f => f ()
dataSourceIsInitialized :: IO Bool
dataSourceStart :: IO ()
dataSourceStop :: forall {f :: * -> *}. Applicative f => f ()
$sel:dataSourceIsInitialized:DataSource :: IO Bool
$sel:dataSourceStart:DataSource :: IO ()
$sel:dataSourceStop:DataSource :: IO ()
..}
loadFile :: FilePath -> IO FileBody
loadFile :: String -> IO FileBody
loadFile String
filePath = do
ByteString
file <- String -> IO ByteString
BSL.readFile String
filePath
let mDecodedFile :: Maybe FileBody
mDecodedFile = ByteString -> Maybe FileBody
forall a. FromJSON a => ByteString -> Maybe a
decode ByteString
file Maybe FileBody -> Maybe FileBody -> Maybe FileBody
forall a. Maybe a -> Maybe a -> Maybe a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ByteString -> Maybe FileBody
forall (m :: * -> *) a.
(MonadThrow m, FromJSON a) =>
ByteString -> m a
Yaml.decodeThrow (ByteString -> ByteString
BSL.toStrict ByteString
file)
case Maybe FileBody
mDecodedFile of
Just !FileBody
fileBody ->
FileBody -> IO FileBody
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileBody
fileBody
Maybe FileBody
Nothing ->
FileBody -> IO FileBody
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure FileBody
forall a. Monoid a => a
mempty