packages feed

reflex-gadt-api 0.2.2.1 → 0.2.2.2

raw patch · 4 files changed

+66/−51 lines, 4 filesdep ~aesondep ~basedep ~bytestringnew-uploaderPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: aeson, base, bytestring, containers, data-default, text

API changes (from Hackage documentation)

- Reflex.Dom.GadtApi.WebSocket: instance GHC.Generics.Generic Reflex.Dom.GadtApi.WebSocket.TaggedRequest
- Reflex.Dom.GadtApi.WebSocket: instance GHC.Generics.Generic Reflex.Dom.GadtApi.WebSocket.TaggedResponse
+ Readme: Dog :: Text -> UTCTime -> Bool -> Maybe Text -> Dog
+ Readme: Token :: Text -> Token
+ Readme: [CatApi_DogApi] :: forall a. Token -> DogApi a -> CatApi a
+ Readme: [CatApi_Identify] :: Text -> CatApi (Either Text Token)
+ Readme: [DogApi_GetByDay] :: Day -> DogApi [Dog]
+ Readme: [DogApi_GetByName] :: Text -> DogApi [Dog]
+ Readme: [DogApi_GetLastSeen] :: DogApi (Maybe Dog)
+ Readme: [DogApi_GetSuspiciousSightings] :: DogApi [Dog]
+ Readme: [DogApi_ReportSighting] :: Text -> Bool -> Maybe Text -> DogApi (Either Text ())
+ Readme: [_dog_imageUri] :: Dog -> Maybe Text
+ Readme: [_dog_name] :: Dog -> Text
+ Readme: [_dog_sighted] :: Dog -> UTCTime
+ Readme: [_dog_suspicious] :: Dog -> Bool
+ Readme: [unToken] :: Token -> Text
+ Readme: catnet :: forall t (m :: Type -> Type). (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) => Token -> Catnet t m (Event t ())
+ Readme: data CatApi a
+ Readme: data Dog
+ Readme: data DogApi a
+ Readme: dogSighting :: forall t (m :: Type -> Type). (DomBuilder t m, MonadHold t m, PostBuild t m, Prerender t m, MonadFix m) => Token -> Catnet t m (Event t (Either Text ()))
+ Readme: instance (c (GHC.Internal.Data.Either.Either Data.Text.Internal.Text Readme.Token), Data.Constraint.Extras.Has c Readme.DogApi) => Data.Constraint.Extras.Has c Readme.CatApi
+ Readme: instance (c [Readme.Dog], c [Readme.Dog], c (GHC.Internal.Maybe.Maybe Readme.Dog), c (GHC.Internal.Data.Either.Either Data.Text.Internal.Text ()), c [Readme.Dog]) => Data.Constraint.Extras.Has c Readme.DogApi
+ Readme: instance Data.Aeson.Types.FromJSON.FromJSON Data.Text.Internal.Text => Data.Aeson.Types.FromJSON.FromJSON (Data.Some.Newtype.Some Readme.CatApi)
+ Readme: instance Data.Aeson.Types.FromJSON.FromJSON Data.Text.Internal.Text => Data.Aeson.Types.FromJSON.FromJSON (Data.Some.Newtype.Some Readme.DogApi)
+ Readme: instance Data.Aeson.Types.FromJSON.FromJSON Readme.Dog
+ Readme: instance Data.Aeson.Types.FromJSON.FromJSON Readme.Token
+ Readme: instance Data.Aeson.Types.ToJSON.ToJSON Data.Text.Internal.Text => Data.Aeson.Types.ToJSON.ToJSON (Readme.CatApi a)
+ Readme: instance Data.Aeson.Types.ToJSON.ToJSON Data.Text.Internal.Text => Data.Aeson.Types.ToJSON.ToJSON (Readme.DogApi a)
+ Readme: instance Data.Aeson.Types.ToJSON.ToJSON Readme.Dog
+ Readme: instance Data.Aeson.Types.ToJSON.ToJSON Readme.Token
+ Readme: instance GHC.Internal.Generics.Generic Readme.Dog
+ Readme: instance GHC.Internal.Generics.Generic Readme.Token
+ Readme: login :: forall t (m :: Type -> Type). (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) => Catnet t m (Event t Token)
+ Readme: main :: IO ()
+ Readme: newtype Token
+ Readme: requestingJs :: forall t (m :: Type -> Type) a. (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))
+ Readme: showDog :: DomBuilder t m => Dog -> m ()
+ Readme: startCatnet :: (Prerender t m, MonadHold t m, MonadIO (Performable m), MonadFix m, DomBuilder t m, PostBuild t m, TriggerEvent t m, PerformEvent t m, Has FromJSON CatApi, forall a. () => ToJSON (CatApi a)) => Either ApiEndpoint WebSocketEndpoint -> m ()
+ Readme: type Catnet t (m :: Type -> Type) = RequesterT t CatApi Either Text m
+ Reflex.Dom.GadtApi.WebSocket: instance GHC.Internal.Generics.Generic Reflex.Dom.GadtApi.WebSocket.TaggedRequest
+ Reflex.Dom.GadtApi.WebSocket: instance GHC.Internal.Generics.Generic Reflex.Dom.GadtApi.WebSocket.TaggedResponse
- Reflex.Dom.GadtApi.WebSocket: mkTaggedResponse :: (Monad m, FromJSON (Some f), Has ToJSON f) => TaggedRequest -> (forall a. f a -> m a) -> m (Either String TaggedResponse)
+ Reflex.Dom.GadtApi.WebSocket: mkTaggedResponse :: (Monad m, FromJSON (Some f), Has ToJSON f) => TaggedRequest -> (forall a. () => f a -> m a) -> m (Either String TaggedResponse)
- 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: performWebSocketRequests :: forall (req :: Type -> Type) 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), 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 :: Type -> Type) 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, MonadJSM m, Has FromJSON api, forall a. ToJSON (api a)) => ApiEndpoint -> RequesterData api -> m (RequesterData (Either Text))
+ Reflex.Dom.GadtApi.XHR: apiRequestXhr :: forall (api :: Type -> Type) 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. (Has FromJSON api, forall a. ToJSON (api a), Prerender t m, Applicative m) => ApiEndpoint -> Event t (RequesterData api) -> m (Event t (RequesterData (Either Text)))
+ Reflex.Dom.GadtApi.XHR: performXhrRequests :: forall t m (api :: Type -> Type). (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 view
@@ -1,9 +1,18 @@ # Revision history for reflex-gadt-api +## 0.2.2.2++* Make Readme part of the library+* Support GHC 9.10+* Loosen version bounds++## 0.2.2.1-r1++* Loosen version bounds+ ## 0.2.2.1  * Support constraints-extras 0.4-* Update obelisk version used by example  ## 0.2.2.0 
Readme.lhs view
@@ -1,9 +1,10 @@ reflex-gadt-api ===============-[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex-gadt-api.svg)](https://hackage.haskell.org/package/reflex-gadt-api) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex-gadt-api/badge)](https://matrix.hackage.haskell.org/#/package/reflex-gadt-api) [![Travis CI](https://api.travis-ci.org/reflex-frp/reflex-gadt-api.svg?branch=develop)](https://travis-ci.org/reflex-frp/reflex-gadt-api) [![Github CI](https://github.com/reflex-frp/reflex-gadt-api/workflows/Haskell%20CI/badge.svg)](https://github.com/reflex-frp/reflex-gadt-api/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex-gadt-api/blob/master/LICENSE) +[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex-gadt-api.svg)](https://hackage.haskell.org/package/reflex-gadt-api) [![Github CI](https://github.com/reflex-frp/reflex-gadt-api/workflows/Haskell%20CI/badge.svg)](https://github.com/reflex-frp/reflex-gadt-api/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex-gadt-api/blob/master/LICENSE)  + This package is designed to be used in full-stack Haskell applications where the API is defined as a GADT, the wire format is JSON, and the frontend is using reflex-dom(-core). reflex-gadt-api provides the basic FRP and encoding/decoding infrastructure to support this architecture.  To serialize the GADT API definition, we use [aeson-gadt-th](https://github.com/obsidiansystems/aeson-gadt-th) with a little help from [constraints-extras](https://github.com/obsidiansystems/constraints-extras).@@ -29,9 +30,9 @@ > {-# LANGUAGE TemplateHaskell #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE UndecidableInstances #-}->+ > module Readme where->+ > import Control.Monad (void) > import Control.Monad.IO.Class (MonadIO) > import Control.Monad.Fix (MonadFix)@@ -39,13 +40,14 @@ > import Data.Aeson.GADT.TH (deriveJSONGADT) > import Data.Constraint.Extras (Has) > import Data.Constraint.Extras.TH (deriveArgDict)+> import Data.Kind (Type) > import Data.Text as T (Text, null, pack) > import Data.Time (UTCTime, Day) > import GHC.Generics (Generic) > import Reflex.Dom.Core > import Reflex.Dom.GadtApi-> + ```  The code that follows would typically go in a common module, since it would be used on the frontend and on the backend. It sets up the basic data type definitions and a couple of GADTs that describe the API.@@ -59,31 +61,31 @@ >   , _dog_imageUri :: Maybe Text >   } >   deriving (Generic)->+ > instance ToJSON Dog > instance FromJSON Dog-> + ```  Here we have an API for retrieving and interacting with the `Dog` data:  ```haskell -> data DogApi :: * -> * where+> data DogApi :: Type -> Type where >   DogApi_GetByDay :: Day -> DogApi [Dog] >   DogApi_GetByName :: Text -> DogApi [Dog] >   DogApi_GetLastSeen :: DogApi (Maybe Dog) >   DogApi_ReportSighting :: Text -> Bool -> Maybe Text -> DogApi (Either Text ()) >   DogApi_GetSuspiciousSightings :: DogApi [Dog]->+ > newtype Token = Token { unToken :: Text } >   deriving (Generic)->+ > instance ToJSON Token > instance FromJSON Token-> + ```  We can take the `DogApi` and embed it in another GADT API. This outer API will handle authentication. (Note that we're not actually implementing a secure authentication scheme or anything here. This is just a toy example.)@@ -93,13 +95,13 @@ > data CatApi a where >   CatApi_Identify :: Text -> CatApi (Either Text Token) >   CatApi_DogApi :: Token -> DogApi a -> CatApi a->+ > deriveJSONGADT ''DogApi > deriveJSONGADT ''CatApi > deriveArgDict ''DogApi > deriveArgDict ''CatApi-> + ```  On the frontend, we'll run a `RequesterT` widget that allows us to emit an event of requests, and we'll transform those requests into XHR calls to the API endpoint.@@ -107,8 +109,8 @@ ```haskell  > type Catnet t m = (RequesterT t CatApi (Either Text) m)-> + ```  This synonym is just here for convenience. The right-hand-side describes a `RequesterT` widget that issues `CatApi` requests and receives responses.  In other words, when we're inside this `RequesterT` we can call the `requesting` function to send API requests and receive responses.@@ -177,8 +179,8 @@ >       rsp <- dogSighting token >       leave <- delay 3 rsp >       pure ((), catnetW token <$ leave) -- Go back to catnet-> + ```  If you're building your frontend in a context where the user interface needs to be susceptible to server-side rendering (for example, if you're using [obelisk](https://github.com/obsidiansystems/obelisk)'s "prerendering" functionality to serve static pages that are "hydrated" once the JS loads), you'll need to wrap any code relying on Javascript (e.g., your XHR requests) in a `prerender`. The function below does this for us.@@ -190,8 +192,8 @@ >   => 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-> + ```  On the login page, we construct a `Behavior` of a `CatApi_Identify` request and send it when the user clicks the submit button.@@ -204,7 +206,7 @@ >   :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) >   => Catnet t m (Event t Token) > login = do->   el "h1" $ text "Identify Yourself"+>   el "h1" $ text "Identify Yourself, Cat" >   cat <- inputElement def >   click <- button "submit" >   rsp <- requestingJs $@@ -213,8 +215,8 @@ >         Right (Right catToken) -> Just catToken >         _ -> Nothing >   pure token-> + ```  This function builds a UI with a few buttons. Depending on which button is clicked, we'll issue an API request and display the result, with one exception: the "Report a Sighting" button click event is returned (and used by the `Workflow` above to navigate to another page).@@ -245,8 +247,8 @@ >     Right dogs -> el "ul" $ mapM_ (el "li" . showDog) dogs >   -- Return the "Report a sighting" click event >   pure addDog-> + ```  The `showDog` widget below does not have `Catnet` or `RequesterT` in its type signature, so we know that it doesn't issue requests. It just builds a display widget for a particular `Dog`.@@ -267,8 +269,8 @@ >   el "dd" $ case _dog_imageUri dog of >     Just img -> elAttr "img" ("src" =: img <> "alt" =: "dog mugshot") blank >     Nothing -> text "None"-> + ```  This rudimentary form allows us to assemble a `Dynamic` `DogApi` request, embed it in a `CatApi` request, and send it.@@ -317,7 +319,7 @@ >     Right (Left err) -> Left err >     Left err -> Left err >     Right (Right result) -> Right result->+ > main :: IO () > main = return () 
Readme.md view
@@ -1,9 +1,10 @@ reflex-gadt-api ===============-[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex-gadt-api.svg)](https://hackage.haskell.org/package/reflex-gadt-api) [![Hackage CI](https://matrix.hackage.haskell.org/api/v2/packages/reflex-gadt-api/badge)](https://matrix.hackage.haskell.org/#/package/reflex-gadt-api) [![Travis CI](https://api.travis-ci.org/reflex-frp/reflex-gadt-api.svg?branch=develop)](https://travis-ci.org/reflex-frp/reflex-gadt-api) [![Github CI](https://github.com/reflex-frp/reflex-gadt-api/workflows/Haskell%20CI/badge.svg)](https://github.com/reflex-frp/reflex-gadt-api/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex-gadt-api/blob/master/LICENSE) +[![Haskell](https://img.shields.io/badge/language-Haskell-orange.svg)](https://haskell.org) [![Hackage](https://img.shields.io/hackage/v/reflex-gadt-api.svg)](https://hackage.haskell.org/package/reflex-gadt-api) [![Github CI](https://github.com/reflex-frp/reflex-gadt-api/workflows/Haskell%20CI/badge.svg)](https://github.com/reflex-frp/reflex-gadt-api/actions) [![BSD3 License](https://img.shields.io/badge/license-BSD3-blue.svg)](https://github.com/reflex-frp/reflex-gadt-api/blob/master/LICENSE)  + This package is designed to be used in full-stack Haskell applications where the API is defined as a GADT, the wire format is JSON, and the frontend is using reflex-dom(-core). reflex-gadt-api provides the basic FRP and encoding/decoding infrastructure to support this architecture.  To serialize the GADT API definition, we use [aeson-gadt-th](https://github.com/obsidiansystems/aeson-gadt-th) with a little help from [constraints-extras](https://github.com/obsidiansystems/constraints-extras).@@ -29,9 +30,9 @@ > {-# LANGUAGE TemplateHaskell #-} > {-# LANGUAGE TypeFamilies #-} > {-# LANGUAGE UndecidableInstances #-}->+ > module Readme where->+ > import Control.Monad (void) > import Control.Monad.IO.Class (MonadIO) > import Control.Monad.Fix (MonadFix)@@ -39,13 +40,14 @@ > import Data.Aeson.GADT.TH (deriveJSONGADT) > import Data.Constraint.Extras (Has) > import Data.Constraint.Extras.TH (deriveArgDict)+> import Data.Kind (Type) > import Data.Text as T (Text, null, pack) > import Data.Time (UTCTime, Day) > import GHC.Generics (Generic) > import Reflex.Dom.Core > import Reflex.Dom.GadtApi-> + ```  The code that follows would typically go in a common module, since it would be used on the frontend and on the backend. It sets up the basic data type definitions and a couple of GADTs that describe the API.@@ -59,31 +61,31 @@ >   , _dog_imageUri :: Maybe Text >   } >   deriving (Generic)->+ > instance ToJSON Dog > instance FromJSON Dog-> + ```  Here we have an API for retrieving and interacting with the `Dog` data:  ```haskell -> data DogApi :: * -> * where+> data DogApi :: Type -> Type where >   DogApi_GetByDay :: Day -> DogApi [Dog] >   DogApi_GetByName :: Text -> DogApi [Dog] >   DogApi_GetLastSeen :: DogApi (Maybe Dog) >   DogApi_ReportSighting :: Text -> Bool -> Maybe Text -> DogApi (Either Text ()) >   DogApi_GetSuspiciousSightings :: DogApi [Dog]->+ > newtype Token = Token { unToken :: Text } >   deriving (Generic)->+ > instance ToJSON Token > instance FromJSON Token-> + ```  We can take the `DogApi` and embed it in another GADT API. This outer API will handle authentication. (Note that we're not actually implementing a secure authentication scheme or anything here. This is just a toy example.)@@ -93,13 +95,13 @@ > data CatApi a where >   CatApi_Identify :: Text -> CatApi (Either Text Token) >   CatApi_DogApi :: Token -> DogApi a -> CatApi a->+ > deriveJSONGADT ''DogApi > deriveJSONGADT ''CatApi > deriveArgDict ''DogApi > deriveArgDict ''CatApi-> + ```  On the frontend, we'll run a `RequesterT` widget that allows us to emit an event of requests, and we'll transform those requests into XHR calls to the API endpoint.@@ -107,8 +109,8 @@ ```haskell  > type Catnet t m = (RequesterT t CatApi (Either Text) m)-> + ```  This synonym is just here for convenience. The right-hand-side describes a `RequesterT` widget that issues `CatApi` requests and receives responses.  In other words, when we're inside this `RequesterT` we can call the `requesting` function to send API requests and receive responses.@@ -177,8 +179,8 @@ >       rsp <- dogSighting token >       leave <- delay 3 rsp >       pure ((), catnetW token <$ leave) -- Go back to catnet-> + ```  If you're building your frontend in a context where the user interface needs to be susceptible to server-side rendering (for example, if you're using [obelisk](https://github.com/obsidiansystems/obelisk)'s "prerendering" functionality to serve static pages that are "hydrated" once the JS loads), you'll need to wrap any code relying on Javascript (e.g., your XHR requests) in a `prerender`. The function below does this for us.@@ -190,8 +192,8 @@ >   => 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-> + ```  On the login page, we construct a `Behavior` of a `CatApi_Identify` request and send it when the user clicks the submit button.@@ -204,7 +206,7 @@ >   :: (DomBuilder t m, MonadHold t m, MonadFix m, Prerender t m) >   => Catnet t m (Event t Token) > login = do->   el "h1" $ text "Identify Yourself"+>   el "h1" $ text "Identify Yourself, Cat" >   cat <- inputElement def >   click <- button "submit" >   rsp <- requestingJs $@@ -213,8 +215,8 @@ >         Right (Right catToken) -> Just catToken >         _ -> Nothing >   pure token-> + ```  This function builds a UI with a few buttons. Depending on which button is clicked, we'll issue an API request and display the result, with one exception: the "Report a Sighting" button click event is returned (and used by the `Workflow` above to navigate to another page).@@ -245,8 +247,8 @@ >     Right dogs -> el "ul" $ mapM_ (el "li" . showDog) dogs >   -- Return the "Report a sighting" click event >   pure addDog-> + ```  The `showDog` widget below does not have `Catnet` or `RequesterT` in its type signature, so we know that it doesn't issue requests. It just builds a display widget for a particular `Dog`.@@ -267,8 +269,8 @@ >   el "dd" $ case _dog_imageUri dog of >     Just img -> elAttr "img" ("src" =: img <> "alt" =: "dog mugshot") blank >     Nothing -> text "None"-> + ```  This rudimentary form allows us to assemble a `Dynamic` `DogApi` request, embed it in a `CatApi` request, and send it.@@ -317,7 +319,7 @@ >     Right (Left err) -> Left err >     Left err -> Left err >     Right (Right result) -> Right result->+ > main :: IO () > main = return () 
reflex-gadt-api.cabal view
@@ -1,12 +1,12 @@ cabal-version:      >=1.10 name:               reflex-gadt-api-version:            0.2.2.1+version:            0.2.2.2 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.  bug-reports:        https://github.com/reflex-frp/reflex-gadt-api/issues-license:            BSD3 +license:            BSD3 license-file:       LICENSE author:             Obsidian Systems maintainer:         maintainer@obsidian.systems@@ -20,26 +20,28 @@ tested-with:        GHC ==8.6.5 || ==8.8.1 || ==8.10.7  library-  hs-source-dirs:   src+  hs-source-dirs:   src, .   build-depends:-      aeson               >=1.4.4  && <1.6+      aeson               >=1.4.4  && <2.3     , aeson-gadt-th       >=0.2.4  && <0.3-    , base                >=4.12   && <4.16-    , bytestring          >=0.10.8 && <0.11+    , base                >=4.12   && <4.21+    , bytestring          >=0.10.8 && <0.13     , constraints-extras  >=0.3.0  && <0.5-    , containers          >=0.6    && <0.7-    , data-default        >=0.6    && <0.8+    , containers          >=0.6    && <0.8+    , data-default        >=0.6    && <0.9     , jsaddle             >=0.9.7  && <0.10-    , reflex              >=0.7    && <0.9+    , reflex              >=0.7    && <1     , reflex-dom-core     >=0.7.0  && <0.9     , some                >=1      && <1.1-    , text                >=1.2    && <1.3+    , text                >=1.2    && <2.2     , time                >=1.6.0  && <2    exposed-modules:     Reflex.Dom.GadtApi     Reflex.Dom.GadtApi.WebSocket     Reflex.Dom.GadtApi.XHR++    Readme    default-language: Haskell2010   ghc-options:      -Wall