-----------------------------------------------------------------------------
-- |
-- Module      :  Miso.Subscription.SSE
-- Copyright   :  (C) 2016-2025 David M. Johnson
-- License     :  BSD3-style (see the file LICENSE)
-- Maintainer  :  David M. Johnson <code@dmj.io>
-- Stability   :  experimental
-- Portability :  non-portable
----------------------------------------------------------------------------
module Miso.Subscription.SSE
 ( -- *** Subscription
   sseSub
   -- *** Types
 , SSE (..)
 ) where
-----------------------------------------------------------------------------
import           Data.Aeson
import qualified Language.Javascript.JSaddle as JSaddle
import           Language.Javascript.JSaddle hiding (new)
-----------------------------------------------------------------------------
import           Miso.Effect (Sub)
import qualified Miso.FFI.Internal as FFI
import           Miso.String
-----------------------------------------------------------------------------
-- | Server-sent events Subscription
sseSub
  :: FromJSON msg
  => MisoString -- ^ EventSource URL
  -> (SSE msg -> action)
  -> Sub action
sseSub :: forall msg action.
FromJSON msg =>
MisoString -> (SSE msg -> action) -> Sub action
sseSub MisoString
url SSE msg -> action
f Sink action
sink = do
  es <- JSM JSVal -> [MisoString] -> JSM JSVal
forall constructor args.
(MakeObject constructor, MakeArgs args) =>
constructor -> args -> JSM JSVal
JSaddle.new (MisoString -> JSM JSVal
forall a. ToJSString a => a -> JSM JSVal
jsg (String -> MisoString
forall str. ToMisoString str => str -> MisoString
ms String
"EventSource")) [MisoString
url]
  FFI.addEventListener es (ms "message") $ \JSVal
v -> do
    dat <- JSVal -> JSM msg
forall json. FromJSON json => JSVal -> JSM json
FFI.jsonParse (JSVal -> JSM msg) -> JSM JSVal -> JSM msg
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< JSVal
v JSVal -> MisoString -> JSM JSVal
forall this name.
(MakeObject this, ToJSString name) =>
this -> name -> JSM JSVal
! (String -> MisoString
forall str. ToMisoString str => str -> MisoString
ms String
"data")
    sink (f (SSEMessage dat))
  FFI.addEventListener es (ms "error") $ \JSVal
_ ->
    Sink action
sink (SSE msg -> action
f SSE msg
forall message. SSE message
SSEError)
  FFI.addEventListener es (ms "close") $ \JSVal
_ ->
    Sink action
sink (SSE msg -> action
f SSE msg
forall message. SSE message
SSEClose)
-----------------------------------------------------------------------------
-- | Server-sent events data
data SSE message
  = SSEMessage message
  | SSEClose
  | SSEError
  deriving (Int -> SSE message -> ShowS
[SSE message] -> ShowS
SSE message -> String
(Int -> SSE message -> ShowS)
-> (SSE message -> String)
-> ([SSE message] -> ShowS)
-> Show (SSE message)
forall message. Show message => Int -> SSE message -> ShowS
forall message. Show message => [SSE message] -> ShowS
forall message. Show message => SSE message -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: forall message. Show message => Int -> SSE message -> ShowS
showsPrec :: Int -> SSE message -> ShowS
$cshow :: forall message. Show message => SSE message -> String
show :: SSE message -> String
$cshowList :: forall message. Show message => [SSE message] -> ShowS
showList :: [SSE message] -> ShowS
Show, SSE message -> SSE message -> Bool
(SSE message -> SSE message -> Bool)
-> (SSE message -> SSE message -> Bool) -> Eq (SSE message)
forall message. Eq message => SSE message -> SSE message -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: forall message. Eq message => SSE message -> SSE message -> Bool
== :: SSE message -> SSE message -> Bool
$c/= :: forall message. Eq message => SSE message -> SSE message -> Bool
/= :: SSE message -> SSE message -> Bool
Eq)
-----------------------------------------------------------------------------