module Hasura.GraphQL.Transport.WebSocket.Types
  ( ErrRespType (ERTGraphqlCompliant, ERTLegacy),
    WSConn,
    WSConnData (WSConnData, _wscOpMap, _wscUser),
    WSConnState (CSInitError, CSInitialised, CSNotInitialised),
    WSServerEnv (..),
    WsClientState (WsClientState, wscsIpAddress, wscsReqHeaders, wscsTokenExpTime, wscsUserInfo),
    WsHeaders (WsHeaders, unWsHeaders),
    SubscriberType (..),
  )
where

import Control.Concurrent.STM qualified as STM
import Data.Time.Clock qualified as TC
import Hasura.GraphQL.Execute qualified as E
import Hasura.GraphQL.Execute.Subscription.State qualified as ES
import Hasura.GraphQL.Transport.HTTP.Protocol
import Hasura.GraphQL.Transport.Instances ()
import Hasura.GraphQL.Transport.WebSocket.Protocol
import Hasura.GraphQL.Transport.WebSocket.Server qualified as WS
import Hasura.Logging qualified as L
import Hasura.Prelude
import Hasura.Server.AppStateRef
import Hasura.Server.Cors
import Hasura.Server.Init.Config (KeepAliveDelay (..))
import Hasura.Server.Metrics (ServerMetrics (..))
import Hasura.Server.Prometheus (PrometheusMetrics (..))
import Hasura.Server.Types (ReadOnlyMode (..))
import Hasura.Session
import Hasura.Tracing qualified as Tracing
import Network.HTTP.Client qualified as HTTP
import Network.HTTP.Types qualified as HTTP
import Network.Wai.Extended qualified as Wai
import StmContainers.Map qualified as STMMap

newtype WsHeaders = WsHeaders {WsHeaders -> [Header]
unWsHeaders :: [HTTP.Header]}
  deriving (Int -> WsHeaders -> ShowS
[WsHeaders] -> ShowS
WsHeaders -> String
(Int -> WsHeaders -> ShowS)
-> (WsHeaders -> String)
-> ([WsHeaders] -> ShowS)
-> Show WsHeaders
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> WsHeaders -> ShowS
showsPrec :: Int -> WsHeaders -> ShowS
$cshow :: WsHeaders -> String
show :: WsHeaders -> String
$cshowList :: [WsHeaders] -> ShowS
showList :: [WsHeaders] -> ShowS
Show, WsHeaders -> WsHeaders -> Bool
(WsHeaders -> WsHeaders -> Bool)
-> (WsHeaders -> WsHeaders -> Bool) -> Eq WsHeaders
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: WsHeaders -> WsHeaders -> Bool
== :: WsHeaders -> WsHeaders -> Bool
$c/= :: WsHeaders -> WsHeaders -> Bool
/= :: WsHeaders -> WsHeaders -> Bool
Eq)

data ErrRespType
  = ERTLegacy
  | ERTGraphqlCompliant
  deriving (Int -> ErrRespType -> ShowS
[ErrRespType] -> ShowS
ErrRespType -> String
(Int -> ErrRespType -> ShowS)
-> (ErrRespType -> String)
-> ([ErrRespType] -> ShowS)
-> Show ErrRespType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ErrRespType -> ShowS
showsPrec :: Int -> ErrRespType -> ShowS
$cshow :: ErrRespType -> String
show :: ErrRespType -> String
$cshowList :: [ErrRespType] -> ShowS
showList :: [ErrRespType] -> ShowS
Show)

data WSConnState
  = -- | headers and IP address from the client for websockets
    CSNotInitialised !WsHeaders !Wai.IpAddress
  | CSInitError !Text
  | CSInitialised !WsClientState
  deriving (Int -> WSConnState -> ShowS
[WSConnState] -> ShowS
WSConnState -> String
(Int -> WSConnState -> ShowS)
-> (WSConnState -> String)
-> ([WSConnState] -> ShowS)
-> Show WSConnState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> WSConnState -> ShowS
showsPrec :: Int -> WSConnState -> ShowS
$cshow :: WSConnState -> String
show :: WSConnState -> String
$cshowList :: [WSConnState] -> ShowS
showList :: [WSConnState] -> ShowS
Show)

data WsClientState = WsClientState
  { -- | the 'UserInfo' required to execute the GraphQL query
    WsClientState -> UserInfo
wscsUserInfo :: !UserInfo,
    -- | the JWT/token expiry time, if any
    WsClientState -> Maybe UTCTime
wscsTokenExpTime :: !(Maybe TC.UTCTime),
    -- | headers from the client (in conn params) to forward to the remote schema
    WsClientState -> [Header]
wscsReqHeaders :: ![HTTP.Header],
    -- | IP address required for 'MonadGQLAuthorization'
    WsClientState -> IpAddress
wscsIpAddress :: !Wai.IpAddress
  }
  deriving (Int -> WsClientState -> ShowS
[WsClientState] -> ShowS
WsClientState -> String
(Int -> WsClientState -> ShowS)
-> (WsClientState -> String)
-> ([WsClientState] -> ShowS)
-> Show WsClientState
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> WsClientState -> ShowS
showsPrec :: Int -> WsClientState -> ShowS
$cshow :: WsClientState -> String
show :: WsClientState -> String
$cshowList :: [WsClientState] -> ShowS
showList :: [WsClientState] -> ShowS
Show)

data WSConnData = WSConnData
  -- the role and headers are set only on connection_init message
  { WSConnData -> TVar WSConnState
_wscUser :: !(STM.TVar WSConnState),
    -- we only care about subscriptions,
    -- the other operations (query/mutations)
    -- are not tracked here
    WSConnData -> OperationMap
_wscOpMap :: !OperationMap,
    WSConnData -> ErrRespType
_wscErrRespTy :: !ErrRespType,
    WSConnData -> GraphQLQueryType
_wscAPIType :: !E.GraphQLQueryType
  }

data WSServerEnv impl = WSServerEnv
  { forall impl. WSServerEnv impl -> Logger Hasura
_wseLogger :: !(L.Logger L.Hasura),
    forall impl. WSServerEnv impl -> SubscriptionsState
_wseSubscriptionState :: !ES.SubscriptionsState,
    forall impl. WSServerEnv impl -> AppStateRef impl
_wseAppStateRef :: AppStateRef impl,
    forall impl. WSServerEnv impl -> Manager
_wseHManager :: !HTTP.Manager,
    forall impl. WSServerEnv impl -> IO CorsPolicy
_wseCorsPolicy :: IO CorsPolicy,
    forall impl. WSServerEnv impl -> ReadOnlyMode
_wseReadOnlyMode :: ReadOnlyMode,
    forall impl. WSServerEnv impl -> WSServer
_wseServer :: !WSServer,
    forall impl. WSServerEnv impl -> KeepAliveDelay
_wseKeepAliveDelay :: !KeepAliveDelay,
    forall impl. WSServerEnv impl -> ServerMetrics
_wseServerMetrics :: !ServerMetrics,
    forall impl. WSServerEnv impl -> PrometheusMetrics
_wsePrometheusMetrics :: !PrometheusMetrics,
    forall impl. WSServerEnv impl -> SamplingPolicy
_wseTraceSamplingPolicy :: !Tracing.SamplingPolicy
  }

data SubscriberType
  = LiveQuerySubscriber !ES.LiveQuerySubscriberDetails
  | StreamingQuerySubscriber !ES.StreamingSubscriberDetails

type OperationMap =
  STMMap.Map OperationId (SubscriberType, Maybe OperationName)

type WSServer = WS.WSServer WSConnData

type WSConn = WS.WSConn WSConnData