-----------------------------------------------------------------------------
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  Miso.Fetch
-- 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 for interacting with the Fetch API <https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API>
-- manually.
--
-- Refer to the miso README if you want to automatically interact with a Servant
-- API.
--
----------------------------------------------------------------------------
module Miso.Fetch
  ( -- ** Function
    fetch
    -- ** Header helpers
  , accept
  , contentType
  , applicationJSON
    -- ** Types
  , Body
  ) where
----------------------------------------------------------------------------
import           Data.Aeson (FromJSON)
import           Language.Javascript.JSaddle (JSVal)
----------------------------------------------------------------------------
import qualified Miso.FFI.Internal as FFI
import           Miso.Effect (Effect, withSink)
import           Miso.String (MisoString)
----------------------------------------------------------------------------
-- | See <https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API>
--
-- @
--
-- data Action
--  = FetchGitHub
--  | SetGitHub GitHub
--  | ErrorHandler MisoString
--  deriving (Show, Eq)
--
-- updateModel :: Action -> Effect Model Action
-- updateModel FetchGitHub =
--   let headers = [ accept =: applicationJSON ]
--   fetch "https://api.github.com" "GET" Nothing headers SetGitHub ErrorHandler
-- updateModel (SetGitHub apiInfo) =
--   info ?= apiInfo
-- updateModel (ErrorHandler msg) =
--  io_ (consoleError msg)
--
-- @
--
fetch
  :: FromJSON result
  => MisoString
  -- ^ url
  -> MisoString
  -- ^ method
  -> Maybe Body
  -- ^ body
  -> [(MisoString, MisoString)]
  -- ^ headers
  -> (result -> action)
  -- ^ successful callback
  -> (MisoString -> action)
  -- ^ errorful callback
  -> Effect parent model action
fetch :: forall result action parent model.
FromJSON result =>
MisoString
-> MisoString
-> Maybe Body
-> [(MisoString, MisoString)]
-> (result -> action)
-> (MisoString -> action)
-> Effect parent model action
fetch MisoString
url MisoString
method Maybe Body
body [(MisoString, MisoString)]
headers result -> action
successful MisoString -> action
errorful =
  (Sink action -> JSM ()) -> Effect parent model action
forall action parent model.
(Sink action -> JSM ()) -> Effect parent model action
withSink ((Sink action -> JSM ()) -> Effect parent model action)
-> (Sink action -> JSM ()) -> Effect parent model action
forall a b. (a -> b) -> a -> b
$ \Sink action
sink ->
    MisoString
-> MisoString
-> Maybe Body
-> [(MisoString, MisoString)]
-> (result -> JSM ())
-> (MisoString -> JSM ())
-> JSM ()
forall action.
FromJSON action =>
MisoString
-> MisoString
-> Maybe Body
-> [(MisoString, MisoString)]
-> (action -> JSM ())
-> (MisoString -> JSM ())
-> JSM ()
FFI.fetch MisoString
url MisoString
method Maybe Body
body [(MisoString, MisoString)]
headers
      (Sink action
sink Sink action -> (result -> action) -> result -> JSM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. result -> action
successful)
      (Sink action
sink Sink action -> (MisoString -> action) -> MisoString -> JSM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MisoString -> action
errorful)
----------------------------------------------------------------------------
type Body = JSVal
----------------------------------------------------------------------------
accept :: MisoString
accept :: MisoString
accept = MisoString
"Accept"
----------------------------------------------------------------------------
contentType :: MisoString
contentType :: MisoString
contentType = MisoString
"Content-Type"
----------------------------------------------------------------------------
applicationJSON :: MisoString
applicationJSON :: MisoString
applicationJSON = MisoString
"application/json"
----------------------------------------------------------------------------