module LaunchDarkly.Server.Config.Internal
( Config (..)
, shouldSendEvents
, ApplicationInfo
, makeApplicationInfo
, withApplicationValue
, getApplicationInfoHeader
) where
import Control.Monad.Logger (LoggingT)
import Data.Generics.Product (getField)
import Data.Set (Set)
import Data.Text (Text)
import qualified Data.Text as T
import GHC.Generics (Generic)
import GHC.Natural (Natural)
import Network.HTTP.Client (Manager)
import Control.Lens ((&))
import Data.List (sortBy)
import Data.Ord (comparing)
import LaunchDarkly.AesonCompat (KeyMap, emptyObject, insertKey, toList)
import qualified LaunchDarkly.AesonCompat as AesonCompat
import LaunchDarkly.Server.DataSource.Internal (DataSourceFactory)
import LaunchDarkly.Server.Reference (Reference)
import LaunchDarkly.Server.Store (PersistentDataStore)
data Config = Config
{ Config -> Text
key :: !Text
, Config -> Text
baseURI :: !Text
, Config -> Text
streamURI :: !Text
, Config -> Text
eventsURI :: !Text
, Config -> Maybe PersistentDataStore
storeBackend :: !(Maybe PersistentDataStore)
, Config -> Natural
storeTTLSeconds :: !Natural
, Config -> Bool
streaming :: !Bool
, Config -> Int
initialRetryDelay :: !Int
, Config -> Bool
allAttributesPrivate :: !Bool
, Config -> Set Reference
privateAttributeNames :: !(Set Reference)
, Config -> Natural
flushIntervalSeconds :: !Natural
, Config -> Natural
pollIntervalSeconds :: !Natural
, Config -> Natural
contextKeyLRUCapacity :: !Natural
, Config -> Natural
eventsCapacity :: !Natural
, Config -> LoggingT IO () -> IO ()
logger :: !(LoggingT IO () -> IO ())
, Config -> Bool
sendEvents :: !Bool
, Config -> Bool
offline :: !Bool
, Config -> Natural
requestTimeoutSeconds :: !Natural
, Config -> Bool
useLdd :: !Bool
, Config -> Maybe DataSourceFactory
dataSourceFactory :: !(Maybe DataSourceFactory)
, Config -> Maybe Manager
manager :: !(Maybe Manager)
, Config -> Maybe ApplicationInfo
applicationInfo :: !(Maybe ApplicationInfo)
, Config -> Bool
omitAnonymousContexts :: !Bool
}
deriving ((forall x. Config -> Rep Config x)
-> (forall x. Rep Config x -> Config) -> Generic Config
forall x. Rep Config x -> Config
forall x. Config -> Rep Config x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Config x -> Config
$cfrom :: forall x. Config -> Rep Config x
Generic)
shouldSendEvents :: Config -> Bool
shouldSendEvents :: Config -> Bool
shouldSendEvents config :: Config
config = (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Config -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"offline" Config
config) Bool -> Bool -> Bool
&& (Config -> Bool
forall (f :: Symbol) a s. HasField' f s a => s -> a
getField @"sendEvents" Config
config)
newtype ApplicationInfo = ApplicationInfo (KeyMap Text) deriving (Int -> ApplicationInfo -> ShowS
[ApplicationInfo] -> ShowS
ApplicationInfo -> String
(Int -> ApplicationInfo -> ShowS)
-> (ApplicationInfo -> String)
-> ([ApplicationInfo] -> ShowS)
-> Show ApplicationInfo
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ApplicationInfo] -> ShowS
$cshowList :: [ApplicationInfo] -> ShowS
show :: ApplicationInfo -> String
$cshow :: ApplicationInfo -> String
showsPrec :: Int -> ApplicationInfo -> ShowS
$cshowsPrec :: Int -> ApplicationInfo -> ShowS
Show, ApplicationInfo -> ApplicationInfo -> Bool
(ApplicationInfo -> ApplicationInfo -> Bool)
-> (ApplicationInfo -> ApplicationInfo -> Bool)
-> Eq ApplicationInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ApplicationInfo -> ApplicationInfo -> Bool
$c/= :: ApplicationInfo -> ApplicationInfo -> Bool
== :: ApplicationInfo -> ApplicationInfo -> Bool
$c== :: ApplicationInfo -> ApplicationInfo -> Bool
Eq)
makeApplicationInfo :: ApplicationInfo
makeApplicationInfo :: ApplicationInfo
makeApplicationInfo = KeyMap Text -> ApplicationInfo
ApplicationInfo KeyMap Text
forall v. KeyMap v
emptyObject
withApplicationValue :: Text -> Text -> ApplicationInfo -> ApplicationInfo
withApplicationValue :: Text -> Text -> ApplicationInfo -> ApplicationInfo
withApplicationValue _ "" info :: ApplicationInfo
info = ApplicationInfo
info
withApplicationValue name :: Text
name value :: Text
value info :: ApplicationInfo
info@(ApplicationInfo map :: KeyMap Text
map)
| (Text
name Text -> [Text] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ["id", "version"]) Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
False = ApplicationInfo
info
| Text -> Int
T.length (Text
value) Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 64 = ApplicationInfo
info
| ((Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` ['a' .. 'z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ ['A' .. 'Z'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ ['0' .. '9'] String -> ShowS
forall a. [a] -> [a] -> [a]
++ ['.', '-', '_']) (Text -> String
T.unpack Text
value)) Bool -> Bool -> Bool
forall a. Eq a => a -> a -> Bool
== Bool
False = ApplicationInfo
info
| Bool
otherwise = KeyMap Text -> ApplicationInfo
ApplicationInfo (KeyMap Text -> ApplicationInfo) -> KeyMap Text -> ApplicationInfo
forall a b. (a -> b) -> a -> b
$ Text -> Text -> KeyMap Text -> KeyMap Text
forall v. Text -> v -> HashMap Text v -> HashMap Text v
insertKey Text
name Text
value KeyMap Text
map
getApplicationInfoHeader :: ApplicationInfo -> Maybe Text
(ApplicationInfo values :: KeyMap Text
values)
| KeyMap Text -> Bool
forall v. KeyMap v -> Bool
AesonCompat.null KeyMap Text
values = Maybe Text
forall a. Maybe a
Nothing
| Bool
otherwise =
KeyMap Text -> [(Text, Text)]
forall v. HashMap Text v -> [(Text, v)]
toList KeyMap Text
values
[(Text, Text)]
-> ([(Text, Text)] -> [(Text, Text)]) -> [(Text, Text)]
forall a b. a -> (a -> b) -> b
& ((Text, Text) -> (Text, Text) -> Ordering)
-> [(Text, Text)] -> [(Text, Text)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (((Text, Text) -> Text) -> (Text, Text) -> (Text, Text) -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Text, Text) -> Text
forall a b. (a, b) -> a
fst)
[(Text, Text)] -> ([(Text, Text)] -> [Text]) -> [Text]
forall a b. a -> (a -> b) -> b
& ((Text, Text) -> Text) -> [(Text, Text)] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text, Text) -> Text
forall a. (Semigroup a, IsString a) => (a, a) -> a
makeTag
[Text] -> ([Text] -> Text) -> Text
forall a b. a -> (a -> b) -> b
& [Text] -> Text
T.unwords
Text -> (Text -> Maybe Text) -> Maybe Text
forall a b. a -> (a -> b) -> b
& Text -> Maybe Text
forall a. a -> Maybe a
Just
where
makeTag :: (a, a) -> a
makeTag (key :: a
key, value :: a
value) = "application-" a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
key a -> a -> a
forall a. Semigroup a => a -> a -> a
<> "/" a -> a -> a
forall a. Semigroup a => a -> a -> a
<> a
value