reflex-gadt-api 0.2.1.0 → 0.2.2.0
raw patch · 6 files changed
+50/−37 lines, 6 filesdep +dependent-sumdep −constraintsdep ~basedep ~reflex-dom-corePVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: dependent-sum
Dependencies removed: constraints
Dependency ranges changed: base, reflex-dom-core
API changes (from Hackage documentation)
+ Reflex.Dom.GadtApi.WebSocket: TaggedRequest :: Int -> Value -> TaggedRequest
+ Reflex.Dom.GadtApi.WebSocket: TaggedResponse :: Int -> Value -> TaggedResponse
- Reflex.Dom.GadtApi.WebSocket: performWebSocketRequests :: forall req js t m. (Prerender js t m, Applicative m, FromJSON (Some req), forall a. ToJSON (req a), ForallF ToJSON req, Has FromJSON req) => WebSocketEndpoint -> Event t (RequesterData req) -> m (Event t (RequesterData (Either Text)))
+ Reflex.Dom.GadtApi.WebSocket: performWebSocketRequests :: forall req t m. (Prerender t m, Applicative m, FromJSON (Some req), forall a. ToJSON (req a), Has FromJSON req) => WebSocketEndpoint -> Event t (RequesterData req) -> m (Event t (RequesterData (Either Text)))
- Reflex.Dom.GadtApi.WebSocket: tagRequests :: forall req t m. (Applicative m, FromJSON (Some req), forall a. ToJSON (req a), ForallF ToJSON req, Has FromJSON req, Monad m, MonadFix m, Reflex t, MonadHold t m) => Event t (RequesterData req) -> Event t TaggedResponse -> m (Event t [TaggedRequest], Event t (RequesterData (Either Text)))
+ Reflex.Dom.GadtApi.WebSocket: tagRequests :: forall req t m. (Applicative m, FromJSON (Some req), forall a. ToJSON (req a), Has FromJSON req, Monad m, MonadFix m, Reflex t, MonadHold t m) => Event t (RequesterData req) -> Event t TaggedResponse -> m (Event t [TaggedRequest], Event t (RequesterData (Either Text)))
- Reflex.Dom.GadtApi.XHR: apiRequestXhr :: forall api m. (MonadIO m, HasJSContext m, MonadJSM m, Has FromJSON api, forall a. ToJSON (api a)) => ApiEndpoint -> RequesterData api -> m (RequesterData (Either Text))
+ Reflex.Dom.GadtApi.XHR: apiRequestXhr :: forall api m. (MonadIO m, MonadJSM m, Has FromJSON api, forall a. ToJSON (api a)) => ApiEndpoint -> RequesterData api -> m (RequesterData (Either Text))
- Reflex.Dom.GadtApi.XHR: performXhrRequests :: forall t m api js. (Has FromJSON api, forall a. ToJSON (api a), Prerender js t m, Applicative m) => ApiEndpoint -> Event t (RequesterData api) -> m (Event t (RequesterData (Either Text)))
+ Reflex.Dom.GadtApi.XHR: performXhrRequests :: forall t m api. (Has FromJSON api, forall a. ToJSON (api a), Prerender t m, Applicative m) => ApiEndpoint -> Event t (RequesterData api) -> m (Event t (RequesterData (Either Text)))
Files
- ChangeLog.md +9/−0
- Readme.lhs +8/−8
- Readme.md +8/−8
- reflex-gadt-api.cabal +9/−5
- src/Reflex/Dom/GadtApi/WebSocket.hs +5/−8
- src/Reflex/Dom/GadtApi/XHR.hs +11/−8
ChangeLog.md view
@@ -1,5 +1,14 @@ # Revision history for reflex-gadt-api +## 0.2.2.0++* Support GHC 8.10+* Make xhr requests non-blocking++## 0.2.1.1++* Expose `Tagged`* constructors+ ## 0.2.1.0 * Use "some" instead of "dependent-sum" package
Readme.lhs view
@@ -119,8 +119,8 @@ ```haskell > startCatnet-> :: forall js t m.-> ( Prerender js t m, MonadHold t m+> :: forall t m.+> ( Prerender t m, MonadHold t m > , MonadIO (Performable m), MonadFix m > , DomBuilder t m, PostBuild t m > , TriggerEvent t m, PerformEvent t m@@ -143,7 +143,7 @@ ``` -The `Event` of responses comes, in this case, from a functoin that will take the requests emitted on the previous line and fetch responses to those requests. It produces an `Event` of responses. We can use either `Reflex.Dom.GadtApi.XHR.performXhrRequests` if we want to send requests using XHR or `Reflex.Dom.GadtApi.WebSocket.performWebSocketRequests` to use WebSockets.+The `Event` of responses comes, in this case, from a function that will take the requests emitted on the previous line and fetch responses to those requests. It produces an `Event` of responses. We can use either `Reflex.Dom.GadtApi.XHR.performXhrRequests` if we want to send requests using XHR or `Reflex.Dom.GadtApi.WebSocket.performWebSocketRequests` to use WebSockets. ```haskell > responses <- case endpoint of@@ -185,7 +185,7 @@ ```haskell > requestingJs-> :: (Reflex t, MonadFix m, Prerender js t m)+> :: (Reflex t, MonadFix m, Prerender t m) > => Event t (Request (Client (Catnet t m)) a) > -> Catnet t m (Event t (Response (Client (Catnet t m)) a)) > requestingJs r = fmap (switch . current) $ prerender (pure never) $ requesting r@@ -200,7 +200,7 @@ ```haskell > login-> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender js t m)+> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) > => Catnet t m (Event t Token) > login = do > el "h1" $ text "Identify Yourself"@@ -221,7 +221,7 @@ ```haskell > catnet-> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender js t m)+> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) > => Token > -> Catnet t m (Event t ()) > catnet token = do@@ -275,7 +275,7 @@ ```haskell > dogSighting-> :: (DomBuilder t m, MonadHold t m, PostBuild t m, Prerender js t m, MonadFix m)+> :: (DomBuilder t m, MonadHold t m, PostBuild t m, Prerender t m, MonadFix m) > => Token > -> Catnet t m (Event t (Either Text ())) > dogSighting token = do@@ -303,7 +303,7 @@ ``` -Once we've got those three values, we can apply them to the `DogApi_ReportSighting` constructor. We're using some infix functoins from [Control.Applicative](https://hackage.haskell.org/package/base/docs/Control-Applicative.html) to apply the constructor to `Dynamic` values, and, as a result, we get a `Dynamic` `DogApi` request. When the submit `Event` fires, we take the `current` value of that `Dynamic` and send it.+Once we've got those three values, we can apply them to the `DogApi_ReportSighting` constructor. We're using some infix functions from [Control.Applicative](https://hackage.haskell.org/package/base/docs/Control-Applicative.html) to apply the constructor to `Dynamic` values, and, as a result, we get a `Dynamic` `DogApi` request. When the submit `Event` fires, we take the `current` value of that `Dynamic` and send it. ```haskell
Readme.md view
@@ -119,8 +119,8 @@ ```haskell > startCatnet-> :: forall js t m.-> ( Prerender js t m, MonadHold t m+> :: forall t m.+> ( Prerender t m, MonadHold t m > , MonadIO (Performable m), MonadFix m > , DomBuilder t m, PostBuild t m > , TriggerEvent t m, PerformEvent t m@@ -143,7 +143,7 @@ ``` -The `Event` of responses comes, in this case, from a functoin that will take the requests emitted on the previous line and fetch responses to those requests. It produces an `Event` of responses. We can use either `Reflex.Dom.GadtApi.XHR.performXhrRequests` if we want to send requests using XHR or `Reflex.Dom.GadtApi.WebSocket.performWebSocketRequests` to use WebSockets.+The `Event` of responses comes, in this case, from a function that will take the requests emitted on the previous line and fetch responses to those requests. It produces an `Event` of responses. We can use either `Reflex.Dom.GadtApi.XHR.performXhrRequests` if we want to send requests using XHR or `Reflex.Dom.GadtApi.WebSocket.performWebSocketRequests` to use WebSockets. ```haskell > responses <- case endpoint of@@ -185,7 +185,7 @@ ```haskell > requestingJs-> :: (Reflex t, MonadFix m, Prerender js t m)+> :: (Reflex t, MonadFix m, Prerender t m) > => Event t (Request (Client (Catnet t m)) a) > -> Catnet t m (Event t (Response (Client (Catnet t m)) a)) > requestingJs r = fmap (switch . current) $ prerender (pure never) $ requesting r@@ -200,7 +200,7 @@ ```haskell > login-> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender js t m)+> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) > => Catnet t m (Event t Token) > login = do > el "h1" $ text "Identify Yourself"@@ -221,7 +221,7 @@ ```haskell > catnet-> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender js t m)+> :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) > => Token > -> Catnet t m (Event t ()) > catnet token = do@@ -275,7 +275,7 @@ ```haskell > dogSighting-> :: (DomBuilder t m, MonadHold t m, PostBuild t m, Prerender js t m, MonadFix m)+> :: (DomBuilder t m, MonadHold t m, PostBuild t m, Prerender t m, MonadFix m) > => Token > -> Catnet t m (Event t (Either Text ())) > dogSighting token = do@@ -303,7 +303,7 @@ ``` -Once we've got those three values, we can apply them to the `DogApi_ReportSighting` constructor. We're using some infix functoins from [Control.Applicative](https://hackage.haskell.org/package/base/docs/Control-Applicative.html) to apply the constructor to `Dynamic` values, and, as a result, we get a `Dynamic` `DogApi` request. When the submit `Event` fires, we take the `current` value of that `Dynamic` and send it.+Once we've got those three values, we can apply them to the `DogApi_ReportSighting` constructor. We're using some infix functions from [Control.Applicative](https://hackage.haskell.org/package/base/docs/Control-Applicative.html) to apply the constructor to `Dynamic` values, and, as a result, we get a `Dynamic` `DogApi` request. When the submit `Event` fires, we take the `current` value of that `Dynamic` and send it. ```haskell
reflex-gadt-api.cabal view
@@ -1,6 +1,6 @@ cabal-version: >=1.10 name: reflex-gadt-api-version: 0.2.1.0+version: 0.2.2.0 synopsis: Interact with a GADT API in your reflex-dom application. description: This package is designed to be used in full-stack Haskell applications where the API is defined as a GADT and the frontend is using reflex-dom.@@ -17,22 +17,21 @@ ChangeLog.md Readme.md -tested-with: GHC ==8.6.5 || ==8.8.1+tested-with: GHC ==8.6.5 || ==8.8.1 || ==8.10.2 library hs-source-dirs: src build-depends: aeson >=1.4.4 && <1.5 , aeson-gadt-th >=0.2.4 && <0.3- , base >=4.12 && <4.14+ , base >=4.12 && <4.16 , bytestring >=0.10.8 && <0.11- , constraints >=0.10.1 && <0.11 , constraints-extras >=0.3.0 && <0.4 , containers >=0.6 && <0.7 , data-default >=0.6 && <0.8 , jsaddle >=0.9.7 && <0.10 , reflex >=0.7 && <0.9- , reflex-dom-core >=0.6.0 && <0.7+ , reflex-dom-core >=0.7.0 && <0.8 , some >=1 && <1.1 , text >=1.2 && <1.3 , time >=1.6.0 && <2@@ -55,6 +54,11 @@ , reflex-gadt-api , text , time+ -- We don't actually need this dependency, but omitting it can cause issues+ -- when an older dependent-sum is used (from before the some package was+ -- split out). Since this is already a transitive dependency, this seems+ -- like the simplest solution.+ , dependent-sum >=0.7 && <0.8 default-language: Haskell2010 main-is: Readme.lhs
src/Reflex/Dom/GadtApi/WebSocket.hs view
@@ -10,8 +10,8 @@ {-# LANGUAGE UndecidableInstances #-} module Reflex.Dom.GadtApi.WebSocket ( performWebSocketRequests- , TaggedRequest- , TaggedResponse+ , TaggedRequest (..)+ , TaggedResponse (..) , mkTaggedResponse , WebSocketEndpoint , tagRequests@@ -19,7 +19,6 @@ import Control.Monad.Fix (MonadFix) import Data.Constraint.Extras-import Data.Constraint.Forall import Data.Aeson import Data.Default import qualified Data.Text as T@@ -59,11 +58,10 @@ -- @ -- performWebSocketRequests- :: forall req js t m.- ( Prerender js t m, Applicative m+ :: forall req t m.+ ( Prerender t m, Applicative m , FromJSON (Some req) , forall a. ToJSON (req a)- , ForallF ToJSON req , Has FromJSON req ) => WebSocketEndpoint@@ -115,7 +113,6 @@ ( Applicative m , FromJSON (Some req) , forall a. ToJSON (req a)- , ForallF ToJSON req , Has FromJSON req , Monad m , MonadFix m@@ -137,7 +134,7 @@ where enc :: forall a. req a -> (Value, Value -> Either Text a) enc r =- ( whichever @ToJSON @req @a $ toJSON r+ ( toJSON r , \x -> case has @FromJSON r $ fromJSON x of Success s-> Right s Error e -> Left $ T.pack e
src/Reflex/Dom/GadtApi/XHR.hs view
@@ -6,14 +6,16 @@ {-# LANGUAGE TypeApplications #-} module Reflex.Dom.GadtApi.XHR where -import Control.Concurrent (newEmptyMVar, putMVar, takeMVar)+import Control.Concurrent (forkIO, newEmptyMVar, putMVar, takeMVar) import Control.Monad.IO.Class (MonadIO, liftIO) import Data.Aeson import qualified Data.ByteString.Lazy as LBS import Data.Constraint.Extras (Has, has)+import Data.Functor (void) import Data.Text (Text) import qualified Data.Text.Encoding as T import Language.Javascript.JSaddle (MonadJSM)+import Language.Javascript.JSaddle.Monad (runJSM, askJSM) import Reflex.Dom.Core type ApiEndpoint = Text@@ -28,25 +30,26 @@ -- @ -- performXhrRequests- :: forall t m api js.+ :: forall t m api. ( Has FromJSON api , forall a. ToJSON (api a)- , Prerender js t m+ , Prerender t m , Applicative m ) => ApiEndpoint -> Event t (RequesterData api) -> m (Event t (RequesterData (Either Text)))-performXhrRequests apiUrl req = fmap switchPromptlyDyn $ prerender (pure never) $- performEventAsync $ ffor req $ \r yield ->- liftIO . yield =<< apiRequestXhr apiUrl r+performXhrRequests apiUrl req = fmap switchPromptlyDyn $ prerender (pure never) $ do+ performEventAsync $ ffor req $ \r yield -> do+ ctx <- askJSM+ void $ liftIO $ forkIO $ flip runJSM ctx $+ liftIO . yield =<< apiRequestXhr apiUrl r -- | Encodes an API request as JSON and issues an 'XhrRequest', -- and attempts to decode the response. apiRequestXhr :: forall api m. ( MonadIO m- , HasJSContext m , MonadJSM m , Has FromJSON api , forall a. ToJSON (api a)@@ -58,7 +61,7 @@ has @FromJSON @api x $ mkRequest x where mkRequest- :: (HasJSContext m, MonadJSM m, FromJSON b)+ :: (MonadJSM m, FromJSON b) => api b -> m (Either Text b) mkRequest req = do