packages feed

yam 0.6.0 → 0.6.1

raw patch · 13 files changed

+347/−67 lines, 13 filesdep +exceptionsdep +http-clientdep +servant-clientdep ~salak

Dependencies added: exceptions, http-client, servant-client, transformers

Dependency ranges changed: salak

Files

README.md view
@@ -15,11 +15,9 @@  ```Haskell -import           Salak import           Salak.Yaml import           Servant import           Yam-import qualified Control.Category    as C import           Data.Version  type API = "hello" :> Get '[PlainText] Text@@ -27,10 +25,6 @@ service :: ServerT API AppSimple service = return "world" -main = runSalakWith "app" YAML $ do-  al <- require  "yam.application"-  sw <- require  "yam.swagger"-  lc <- requireD "yam.logging"-  start al sw (makeVersion []) lc spanNoNotifier emptyAM serveWarp (Proxy @API) service+main = start "app" YAML (makeVersion []) (return emptyAM) (Proxy @API) (return service)  ```
src/Yam.hs view
@@ -17,6 +17,7 @@    -- * Yam Server     start+  , start'   , serveWarp   -- ** Application Configuration   , AppConfig(..)@@ -36,6 +37,10 @@   , simpleConfig   , simpleConfig'   , simpleMiddleware+  -- *** Health+  , HealthStatus(..)+  , HealthResult(..)+  , mergeHealth   -- * Modules   -- ** Logger   , LogConfig(..)@@ -52,6 +57,7 @@   , SwaggerConfig(..)   , serveWithContextAndSwagger   , baseInfo+  , SwaggerTag   -- * Reexport   , spanNoNotifier   , Span(..)@@ -67,11 +73,18 @@   , liftIO   , fromMaybe   , throw+  , logInfo+  , logError+  , logWarn+  , logDebug+  , RunSalak(..)   ) where  import qualified Control.Category               as C+import           Control.Monad.IO.Unlift import           Control.Monad.Logger.CallStack import           Data.Opentracing+import           Data.Text                      (pack) import           Network.Wai import           Salak import           Servant@@ -79,66 +92,70 @@ import           Yam.App import           Yam.Config import           Yam.Logger+import           Yam.Middleware import           Yam.Middleware.Error import           Yam.Middleware.Trace import           Yam.Prelude+import           Yam.Server+import           Yam.Server.Health import           Yam.Swagger --- | Application Middleware.-newtype AppMiddleware a b = AppMiddleware-  { runAM :: Context a -> Middleware -> (Context b -> Middleware -> LoggingT IO ()) -> LoggingT IO () }--instance C.Category AppMiddleware where-  id = AppMiddleware $ \a m f -> f a m-  (AppMiddleware fbc) . (AppMiddleware fab) = AppMiddleware $ \a m f -> fab a m $ \b m1 -> fbc b m1 f---- | Simple Application Middleware, just provide a config to context.-simpleContext :: a -> AppMiddleware cxt (a ': cxt)-simpleContext a = AppMiddleware $ \c m f -> f (a :. c) m---- | Simple Application Middleware, just provide a config to context.-simpleConfig' :: (HasSalak cxt, FromProp a) => Text -> (a -> AppT cxt (LoggingT IO) b) -> AppMiddleware cxt (b ': cxt)-simpleConfig' key g = AppMiddleware $ \c m f -> runAppT c (require key) >>= \a -> runAppT c (g a) >>= \b -> f (b :. c) m---- | Simple Application Middleware, just provide a config to context.-simpleConfig :: (HasSalak cxt, FromProp a) => Text -> AppMiddleware cxt (a ': cxt)-simpleConfig key = simpleConfig' key return---- | Simple Application Middleware, promote a 'Middleware' to 'AppMiddleware'-simpleMiddleware :: Middleware -> AppMiddleware cxt cxt-simpleMiddleware m = AppMiddleware $ \c m2 f -> f c (m . m2)- -- | Standard Starter of Yam. start-  :: forall api cxt-  . ( HasServer api cxt+  :: forall file api cxt+  . ( HasLoad file+    , HasLogger cxt+    , HasServer api  cxt     , HasSwagger api)-  => AppConfig -- ^ Application Config-  -> SwaggerConfig -- ^ SwaggerConfig-  -> Version -- ^ Application Version-  -> IO LogConfig -- ^ Logger Config-  -> (Span -> AppV cxt IO ()) -- ^ Opentracing notifier-  -> AppMiddleware Simple cxt -- ^ Application Middleware-  -> (AppConfig -> Application -> IO ()) -- ^ Run Application+  => String -- ^ File config name+  -> file -- ^ Config file format+  -> Version -- ^ Version+  -> RunSalak (AppMiddleware Simple cxt) -- ^ Application Middleware   -> Proxy api -- ^ Application API Proxy-  -> ServerT api (AppV cxt IO) -- ^ Application API Server+  -> RunSalak (ServerT api (AppV cxt IO)) -- ^ Application API Server   -> IO ()-start ac@AppConfig{..} sw@SwaggerConfig{..} vs logConfig f am runHttp p api =-  withLogger name logConfig $ \logger -> do-    logInfo $ "Start Service [" <> name <> "] ..."+start cfg file = start' (loadSalakFile cfg file)++-- | Standard Starter of Yam.+start'+  :: forall api cxt+  .(HasLogger cxt+  , HasServer api  cxt+  , HasSwagger api)+  => LoadSalakT IO ()+  -> Version+  -> RunSalak (AppMiddleware Simple cxt)+  -> Proxy api+  -> RunSalak (ServerT api (AppV cxt IO))+  -> IO ()+start' load ver mkAMD pSer mkSer = loadAndRunSalak load $ do+  c                    <- requireD "logging"+  app@AppConfig{..}    <- require  "application"+  sw@SwaggerConfig{..} <- require  "swagger"+  withLogger name c $ \logger -> unSalak $ do     let portText = showText port-        baseCxt  = LF logger :. EmptyContext-    runAM am baseCxt id $ \cxt middleware -> do+        baseCxt = (LF logger :. EmptyContext)+    logInfo $ "Start Service [" <> name <> "] ..."+    amd <- mkAMD+    ser <- mkSer+    f   <- askUnliftIO+    liftX $ runAM amd baseCxt id emptyHealth $ \cxt middleware hr -> lift $ unliftIO f $ do+      (en, aep) <- actuatorEndpoint hr+      readLogs >>= mapM_ (logInfo . ("Parsing " <>))       when enabled $         logInfo    $ "Swagger enabled: http://localhost:" <> portText <> "/" <> pack urlDir       logInfo      $ "Servant started on port(s): "       <> portText-      liftIO-        $ runHttp ac-        $ traceMiddleware (\v -> runAppT (VH v :. cxt) . f)-        $ middleware-        $ errorMiddleware baseCxt-        $ serveWithContextAndSwagger sw (baseInfo hostname name vs port) (Proxy @(Vault :> api)) cxt-        $ \v -> hoistServerWithContext p (Proxy @cxt) (nt cxt v) api+      let go :: forall a. (HasSwagger a, HasServer a cxt) => Proxy a -> ServerT a (AppV cxt IO) -> RunSalak ()+          go x y = liftIO+            $ serveWarp app+            $ traceMiddleware (\v -> runAppT (VH v :. cxt) . spanNoNotifier)+            $ middleware+            $ errorMiddleware baseCxt+            $ serveWithContextAndSwagger sw (baseInfo hostname name ver port) (Proxy @(Vault :> a)) cxt+            $ \v -> hoistServerWithContext x (Proxy @cxt) (nt cxt v) y+      if en+        then go (Proxy @(api :<|> ActuatorEndpoint)) (ser :<|> aep)+        else go pSer ser  -- | default http server by warp. serveWarp :: AppConfig -> Application -> IO ()@@ -166,11 +183,9 @@  -- $use ----- > import           Salak -- > import           Salak.Yaml -- > import           Servant -- > import           Yam--- > import qualified Control.Category    as C -- > import           Data.Version -- > -- > type API = "hello" :> Get '[PlainText] Text@@ -178,9 +193,5 @@ -- > service :: ServerT API AppSimple -- > service = return "world" -- >--- > main = runSalakWith "app" YAML $ do--- >   al <- require  "yam.application"--- >   sw <- require  "yam.swagger"--- >   lc <- requireD "yam.logging"--- >   start al sw (makeVersion []) lc spanNoNotifier emptyAM serveWarp (Proxy @API) service+-- > main = start "app" YAML (makeVersion []) (return emptyAM) (Proxy @API) (return service) 
src/Yam/App.hs view
@@ -19,6 +19,9 @@ -- | Application with 'Vault' type AppV cxt = AppT (VaultHolder : cxt) +-- | Application with 'SourcePack'+type AppS cxt = AppV (SourcePack : cxt)+ instance MonadTrans (AppT cxt) where   lift = AppT . lift 
src/Yam/Logger.hs view
@@ -9,7 +9,7 @@   , LogFuncHolder(..)   , VaultHolder(..)   ) where-+import           Control.Monad.IO.Unlift import           Control.Monad.Logger.CallStack import qualified Data.Vault.Lazy                as L import           Data.Word@@ -70,8 +70,10 @@         let locate = if ll /= LevelError then "" else " @" <> toLogStr loc_filename <> toLogStr (show loc_start)         in toLogStr t <> " " <> toStr ll <> xn <> toLogStr loc_module <> locate <> " - " <> s <> "\n" -withLogger :: Text -> IO LogConfig -> (LogFunc -> LoggingT IO a) -> IO a-withLogger n lc action = bracket (newLogger n lc) snd $ \(f,_) -> runLoggingT (askLoggerIO >>= action) f+withLogger :: (MonadUnliftIO m) => Text -> IO LogConfig -> (LogFunc -> LoggingT m a) -> m a+withLogger n lc action = do+  f <- askRunInIO+  liftIO $ bracket (newLogger n lc) (snd) $ f . runLoggingT (askLoggerIO >>= action) . fst  addTrace :: LogFunc -> Text -> LogFunc addTrace f tid a b c d = let p = "[" <> toLogStr tid <> "] " in f a b c (p <> d)
+ src/Yam/Middleware.hs view
@@ -0,0 +1,34 @@+module Yam.Middleware where++import qualified Control.Category               as C+import           Control.Monad.Logger.CallStack+import           Data.Text                      (Text)+import           Network.Wai+import           Salak+import           Servant+import           Yam.App+import           Yam.Server.Health++-- | Application Middleware.+newtype AppMiddleware a b = AppMiddleware+  { runAM :: Context a -> Middleware -> IO HealthResult -> (Context b -> Middleware -> IO HealthResult -> LoggingT IO ()) -> LoggingT IO () }++instance C.Category AppMiddleware where+  id = AppMiddleware $ \a m h f -> f a m h+  (AppMiddleware fbc) . (AppMiddleware fab) = AppMiddleware $ \a m h f -> fab a m h $ \b m1 h1 -> fbc b m1 h1 f++-- | Simple Application Middleware, just provide a config to context.+simpleContext :: a -> AppMiddleware cxt (a ': cxt)+simpleContext a = AppMiddleware $ \c m h f -> f (a :. c) m h++-- | Simple Application Middleware, just provide a config to context.+simpleConfig' :: (HasSalak cxt, FromProp a) => Text -> (a -> AppT cxt (LoggingT IO) b) -> AppMiddleware cxt (b ': cxt)+simpleConfig' key g = AppMiddleware $ \c m h f -> runAppT c (require key) >>= \a -> runAppT c (g a) >>= \b -> f (b :. c) m h++-- | Simple Application Middleware, just provide a config to context.+simpleConfig :: (HasSalak cxt, FromProp a) => Text -> AppMiddleware cxt (a ': cxt)+simpleConfig key = simpleConfig' key return++-- | Simple Application Middleware, promote a 'Middleware' to 'AppMiddleware'+simpleMiddleware :: Middleware -> AppMiddleware cxt cxt+simpleMiddleware m = AppMiddleware $ \c m2 h f -> f c (m . m2) h
+ src/Yam/Middleware/Client.hs view
@@ -0,0 +1,61 @@+{-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+module Yam.Middleware.Client(+    HttpClient+  , HasHttpClient+  , runClient+  , hoistC+  , clientMiddleware+  , clientMiddleware'+  ) where++import           Data.Default+import           Data.Proxy+import           Network.HTTP.Client hiding (Proxy)+import           Salak+import           Servant+import           Servant.Client+import           Yam.App+import           Yam.Logger+import           Yam.Middleware+import           Yam.Prelude++instance Default ManagerSettings where+  def = defaultManagerSettings++instance FromProp ResponseTimeout where+  fromProp = responseTimeoutMicro <$> fromProp++instance FromProp ManagerSettings where+  fromProp = do+    connCount <- "max-conns"  .?: managerConnCount+    timeout   <- "timeout"    .?: managerResponseTimeout+    idleCount <- "idle-conns" .?: managerIdleConnectionCount+    return def+      { managerConnCount           = connCount+      , managerResponseTimeout     = timeout+      , managerIdleConnectionCount = idleCount+      }++data HttpClient = HttpClient Manager++type HasHttpClient cxt = (HasLogger cxt, HasContextEntry cxt HttpClient)++runClient :: HasHttpClient cxt => Proxy cxt -> BaseUrl -> ClientM a -> AppT cxt IO a+runClient _ url cma = do+  HttpClient m <- getEntry+  v <- liftIO $ runClientM cma (mkClientEnv m url)+  case v of+    Left  e -> throwS err400 $ showText e+    Right r -> return r++hoistC :: forall cxt api. (HasHttpClient cxt, HasClient ClientM api) => Proxy cxt -> Proxy api -> BaseUrl -> Client (AppT cxt IO) api+hoistC pc p url = hoistClient p (runClient pc url) (client p)++clientMiddleware :: RunSalak (AppMiddleware cxt (HttpClient : cxt))+clientMiddleware = clientMiddleware' id++clientMiddleware' :: (ManagerSettings -> ManagerSettings) -> RunSalak (AppMiddleware cxt (HttpClient : cxt))+clientMiddleware' f = do+  ms <- require "client" >>= liftIO . newManager . f+  return $ simpleContext $ HttpClient ms
src/Yam/Middleware/Error.hs view
@@ -1,6 +1,8 @@ {-# OPTIONS_GHC -fno-warn-orphans #-}+{-# LANGUAGE ImplicitParams #-} module Yam.Middleware.Error where +import           Control.Monad.Logger.CallStack import           Network.Wai import           Servant import           Yam.App@@ -10,4 +12,4 @@ errorMiddleware :: HasLogger cxt => Context cxt -> Middleware errorMiddleware cxt app req resH = app req resH `catch` (\e -> go e >> resH (whenException e))   where-    go = runVault cxt (vault req) . logError . showText+    go = runVault cxt (vault req) . logErrorCS ?callStack . showText
src/Yam/Prelude.hs view
@@ -23,6 +23,7 @@   , try   , catch   , when+  , lift   , (<>)   , LogLevel(..)   , logInfo@@ -40,6 +41,9 @@   , fromJust   , Version   , Middleware+  , RunSalak(..)+  , liftSalak+  , liftX   ) where  import           Control.Exception                   hiding (Handler)@@ -63,10 +67,41 @@ import           Data.Word import           GHC.Stack import           Network.Wai+import           Salak import           Servant import           Servant.Server.Internal.ServerError import           System.IO.Unsafe                    (unsafePerformIO) import           System.Random.MWC++newtype RunSalak a = RunSalak { unSalak :: LoggingT (RunSalakT IO) a } deriving (Functor, Applicative, Monad)++instance HasSourcePack RunSalak where+  askSourcePack = liftSalak askSourcePack+  logSP         = liftSalak . logSP+  readLogs      = liftSalak readLogs++instance MonadIO RunSalak where+  liftIO = RunSalak . liftIO++instance MonadLogger RunSalak where+  monadLoggerLog a b c d = RunSalak (monadLoggerLog a b c d)++instance MonadLoggerIO RunSalak where+  askLoggerIO = RunSalak askLoggerIO++instance MonadUnliftIO RunSalak where+  askUnliftIO = RunSalak $ do+    f  <- lift askUnliftIO+    lf <- askLoggerIO+    return $ UnliftIO $ \ma -> unliftIO f (runLoggingT (unSalak ma) lf)++liftSalak :: RunSalakT IO a -> RunSalak a+liftSalak = RunSalak . lift++liftX :: LoggingT IO a -> RunSalak a+liftX f = do+  lf <- askLoggerIO+  liftIO $ runLoggingT f lf  type LogFunc = Loc -> LogSource -> LogLevel -> LogStr -> IO () 
+ src/Yam/Server.hs view
@@ -0,0 +1,38 @@+module Yam.Server(+    actuatorEndpoint+  , ActuatorEndpoint+  ) where++import           Salak+import           Servant+import           Yam.App+import           Yam.Logger+import           Yam.Prelude+import           Yam.Server.Health+import           Yam.Server.Refresh+import           Yam.Swagger++data ActuatorConfig = ActuatorConfig+  { enabled :: Bool+  , refresh :: Bool+  , health  :: Bool+  }++instance FromProp ActuatorConfig where+  fromProp = ActuatorConfig+    <$> "enabled"         .?= False+    <*> "refresh.enabled" .?= True+    <*> "health.enabled"  .?= True++type ActuatorEndpoint = SwaggerTag "actuator" "Actuator API" :> "actuator" :>+  (    RefreshEndpoint+  :<|> HealthEndpoint+  )++endpoint :: HasLogger cxt => ActuatorConfig -> IO HealthResult -> IO ReloadResult -> ServerT ActuatorEndpoint (AppV cxt IO)+endpoint ActuatorConfig{..} hr rr = refreshEndpoint rr refresh :<|> healthEndpoint hr health++actuatorEndpoint ::  HasLogger cxt => IO HealthResult -> RunSalak (Bool, ServerT ActuatorEndpoint (AppV cxt IO))+actuatorEndpoint hr = do+  ac@ActuatorConfig{..} <- require "actuator"+  (enabled,) <$> liftSalak (exec $ return . endpoint ac hr)
+ src/Yam/Server/Health.hs view
@@ -0,0 +1,36 @@+{-# LANGUAGE DeriveAnyClass #-}+module Yam.Server.Health where++import           Data.Aeson+import qualified Data.HashMap.Strict as M+import           Data.Swagger+import           GHC.Generics+import           Servant+import           Yam.App+import           Yam.Prelude++type HealthEndpoint = "health" :> Get '[JSON] HealthResult++data HealthStatus = UP | DOWN deriving (Eq, Show, Generic, ToJSON)++instance ToSchema HealthStatus+instance ToSchema HealthResult++data HealthResult = HealthResult+  { status  :: HealthStatus+  , errMsg  :: Maybe String+  , details :: M.HashMap Text HealthResult+  } deriving (Eq, Show, Generic, ToJSON)++emptyHealth :: IO HealthResult+emptyHealth = return (HealthResult UP Nothing M.empty)++mergeHealth :: IO HealthStatus -> Text -> IO HealthResult -> IO HealthResult+mergeHealth ios na ior = do+  (err,s)          <- ((Nothing,) <$> ios) `catch` (\(e :: SomeException) -> return (Just (show e), DOWN))+  HealthResult{..} <- ior+  return (HealthResult (if s == DOWN then s else status) Nothing $ M.insert na (HealthResult s err M.empty) details)++healthEndpoint :: MonadIO m => IO HealthResult -> Bool -> AppT cxt m HealthResult+healthEndpoint a True = liftIO a+healthEndpoint a _    = liftIO a
+ src/Yam/Server/Refresh.hs view
@@ -0,0 +1,21 @@+module Yam.Server.Refresh where++import           Data.Text   (Text, pack)+import           Salak+import           Servant+import           Yam.App+import           Yam.Logger+import           Yam.Prelude++type RefreshEndpoint = "refresh" :> Post '[PlainText] Text++refreshEndpoint :: (HasLogger cxt, MonadIO m) => IO ReloadResult -> Bool -> AppT cxt m Text+refreshEndpoint io True = do+  ReloadResult{..} <- liftIO $ io+  if isError+    then throwS err400 $ showMsg msg+    else return $ showMsg msg+refreshEndpoint _ _     = throwS err401 "Refresh not allowed"++showMsg :: [String] -> Text+showMsg = pack . unlines
src/Yam/Swagger.hs view
@@ -3,14 +3,17 @@     SwaggerConfig(..)   , serveWithContextAndSwagger   , baseInfo+  , SwaggerTag   ) where  import           Control.Lens       hiding (Context) import           Data.Reflection import           Data.Swagger import           Data.Version       (showVersion)+import           GHC.TypeLits import           Salak import           Servant+import           Servant.Client import           Servant.Swagger import           Servant.Swagger.UI import           Yam.Prelude@@ -59,5 +62,27 @@   & info . version .~ pack (showVersion v)   & host ?~ Host hostName (Just $ fromIntegral p) +data SwaggerTag (name :: Symbol) (desp :: Symbol) +instance HasServer api ctx+  => HasServer (SwaggerTag name desp :> api) ctx where+  type ServerT (SwaggerTag name desp :> api) m = ServerT api m+  route _ = route (Proxy @api)+  hoistServerWithContext _ = hoistServerWithContext (Proxy @api)++instance HasClient m api+  => HasClient m (SwaggerTag name desp :> api) where+  type  Client m (SwaggerTag name desp :> api) = Client m api+  clientWithRoute _ _ = clientWithRoute (Proxy @m) (Proxy @api)+  hoistClientMonad pm _ = hoistClientMonad pm (Proxy @api)++instance (HasSwagger api, KnownSymbol name, KnownSymbol desp)+  => HasSwagger (SwaggerTag name desp :> api) where+  toSwagger _ = toSwagger (Proxy @api) & applyTags [tag]+    where+      tag = Tag (go (Proxy @name)) (g2 $ go (Proxy @desp)) Nothing+      go :: forall a. KnownSymbol a => Proxy a -> Text+      go  = pack . symbolVal+      g2 "" = Nothing+      g2 a  = Just a 
yam.cabal view
@@ -1,6 +1,6 @@ cabal-version: 1.12 name: yam-version: 0.6.0+version: 0.6.1 license: BSD3 license-file: LICENSE copyright: (c) 2018 Daniel YU@@ -19,6 +19,7 @@ library     exposed-modules:         Yam+        Yam.Middleware.Client     hs-source-dirs: src     other-modules:         Yam.Swagger@@ -26,8 +27,12 @@         Yam.App         Yam.Prelude         Yam.Config+        Yam.Middleware         Yam.Middleware.Trace         Yam.Middleware.Error+        Yam.Server+        Yam.Server.Refresh+        Yam.Server.Health         Data.Opentracing         Data.Opentracing.Types         Data.Opentracing.Tracer@@ -53,7 +58,9 @@         binary >=0.8.6.0 && <0.9,         bytestring >=0.10.8.2 && <0.11,         data-default >=0.7.1.1 && <0.8,+        exceptions >=0.10.1 && <0.11,         fast-logger >=2.4.15 && <2.5,+        http-client >=0.6.4 && <0.7,         http-types >=0.12.3 && <0.13,         lens ==4.17.*,         menshen >=0.0.3 && <0.1,@@ -61,13 +68,15 @@         mtl >=2.2.2 && <2.3,         mwc-random >=0.14.0.0 && <0.15,         reflection >=2.1.4 && <2.2,-        salak >=0.2.9 && <0.3,+        salak >=0.2.9.3 && <0.3,         scientific >=0.3.6.2 && <0.4,+        servant-client ==0.16.*,         servant-server ==0.16.*,         servant-swagger >=1.1.7 && <1.2,         servant-swagger-ui >=0.3.2.3.19.3 && <0.4,         swagger2 >=2.3.1.1 && <2.4,         text >=1.2.3.1 && <1.3,+        transformers >=0.5.6.2 && <0.6,         unliftio-core >=0.1.2.0 && <0.2,         unordered-containers >=0.2.10.0 && <0.3,         vault >=0.3.1.2 && <0.4,@@ -88,9 +97,14 @@         Yam.App         Yam.Config         Yam.Logger+        Yam.Middleware+        Yam.Middleware.Client         Yam.Middleware.Error         Yam.Middleware.Trace         Yam.Prelude+        Yam.Server+        Yam.Server.Health+        Yam.Server.Refresh         Yam.Swagger         Paths_yam     default-language: Haskell2010@@ -115,8 +129,10 @@         binary >=0.8.6.0 && <0.9,         bytestring >=0.10.8.2 && <0.11,         data-default >=0.7.1.1 && <0.8,+        exceptions >=0.10.1 && <0.11,         fast-logger >=2.4.15 && <2.5,         hspec ==2.*,+        http-client >=0.6.4 && <0.7,         http-types >=0.12.3 && <0.13,         lens ==4.17.*,         menshen >=0.0.3 && <0.1,@@ -124,13 +140,15 @@         mtl >=2.2.2 && <2.3,         mwc-random >=0.14.0.0 && <0.15,         reflection >=2.1.4 && <2.2,-        salak >=0.2.9 && <0.3,+        salak >=0.2.9.3 && <0.3,         scientific >=0.3.6.2 && <0.4,+        servant-client ==0.16.*,         servant-server ==0.16.*,         servant-swagger >=1.1.7 && <1.2,         servant-swagger-ui >=0.3.2.3.19.3 && <0.4,         swagger2 >=2.3.1.1 && <2.4,         text >=1.2.3.1 && <1.3,+        transformers >=0.5.6.2 && <0.6,         unliftio-core >=0.1.2.0 && <0.2,         unordered-containers >=0.2.10.0 && <0.3,         vault >=0.3.1.2 && <0.4,