Runtime.purs 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. module Browser.Runtime (Port, connect, onConnectAddListener, portOnDisconnect, postMessage, postMessageJson, onMessageAddListener, onMessageJsonAddListener, onMessageRemoveListener) where
  2. import Browser.Utils (mkListenerOne, Listener, UnregisteredListener)
  3. import Control.Alt (map)
  4. import Control.Monad.Except (runExcept)
  5. import Data.Array (intercalate)
  6. import Data.Either (Either(..))
  7. import Data.Eq (class Eq)
  8. import Data.Generic.Rep (class Generic)
  9. import Data.Monoid ((<>))
  10. import Effect (Effect)
  11. import Effect.Console (error)
  12. import Foreign (renderForeignError)
  13. import Foreign.Generic (class GenericEncode, class GenericDecode, defaultOptions, genericEncodeJSON, genericDecodeJSON)
  14. import Prelude (Unit, ($), bind, discard, pure)
  15. foreign import data Port :: Type
  16. foreign import portEquality :: Port -> Port -> Boolean
  17. instance eqPort :: Eq Port where
  18. eq = portEquality
  19. foreign import connect :: Effect Port
  20. foreign import onConnectAddListener :: Listener Port -> Effect Unit
  21. foreign import postMessage :: forall a. Port -> a -> Effect Unit
  22. postMessageJson :: forall a rep. Generic a rep => GenericEncode rep => Port -> a -> Effect Unit
  23. postMessageJson port d = postMessage port $ genericEncodeJSON (defaultOptions { unwrapSingleConstructors = true}) d
  24. foreign import portOnDisconnect :: Port -> Listener Unit -> Effect Unit
  25. foreign import onMessageAddListener :: forall a. Port -> Listener a -> Effect Unit
  26. onMessageJsonAddListener :: forall a rep. Generic a rep => GenericDecode rep => Port -> UnregisteredListener a -> Effect (Listener String)
  27. onMessageJsonAddListener port f = do
  28. jsonLst <- mkListenerOne listener
  29. onMessageAddListener port jsonLst
  30. pure jsonLst
  31. where
  32. listener msg = case runExcept (genericDecodeJSON (defaultOptions { unwrapSingleConstructors = true}) msg :: _ a) of
  33. Left err -> do
  34. error $ "error while trying to parse message: " <> intercalate ", " (map renderForeignError err)
  35. error $ "message was " <> msg
  36. Right d -> f d
  37. foreign import onMessageRemoveListener :: forall a. Port -> Listener a -> Effect Unit