@@ -6,9 +6,10 @@ import Affjax as AX
66import Affjax.RequestBody as RequestBody
77import Affjax.RequestHeader (RequestHeader(..))
88import Affjax.ResponseFormat as ResponseFormat
9−import Control.Monad.Error.Class (class MonadError, class MonadThrow)
9+import Control.Monad.Error.Class (class MonadThrow)
1010import Data.Either (Either(..))
1111import Data.HTTP.Method (Method(..))
12+import Data.List.Types (NonEmptyList)
1213import Data.Maybe (Maybe(..))
1314import Data.MediaType (MediaType(..))
1415import Data.String as String
@@ -17,35 +18,113 @@ import Effect.Aff (Aff, error, throwError)
1718import Effect.Aff.Class (class MonadAff, liftAff)
1819import Effect.Class (liftEffect)
1920import Effect.Class.Console as Log
21+import Foreign (ForeignError)
2022import Simple.JSON as JSON
2123import Type.Proxy (Proxy(..))
2224
2325data GraphQL
2426
25−data Gql (operation :: GraphQL)
26− = Gql
27+data Gql (operation :: GraphQL) = Gql
2728
28−class GraphQLReqRes (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) | operation -> gql i o
29+class
30+ GraphQLReqRes
31+ (operation :: GraphQL)
32+ (gql :: Symbol)
33+ (i :: Row Type)
34+ (o :: Row Type)
35+ | operation -> gql i o
2936
3037type Endpoint = String
38+type NetworkErrorInfo =
39+ { endpoint :: Endpoint
40+ , requestHeaders :: Array RequestHeader
41+ , requestBody :: String
42+ , error :: AX.Error
43+ }
3144
32−type GraphQLClient' (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) (m :: Type -> Type) (e :: Type) = GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => MonadAff m => MonadThrow e m => MonadError e m => (AX.Error -> e) -> (AX.Response String -> e) ->Gql operation -> Record i -> m { | o }
45+type ParsingErrorInfo =
46+ { endpoint :: Endpoint
47+ , requestHeaders :: Array RequestHeader
48+ , requestBody :: String
49+ , response :: AX.Response String
50+ , jsonParsingError :: NonEmptyList ForeignError
51+ }
3352
34−type GraphQLClient = forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) (m :: Type -> Type) (e :: Type). GraphQLClient' operation gql i o m e
53+type GraphQLClient'
54+ (operation :: GraphQL)
55+ (gql :: Symbol)
56+ (i :: Row Type)
57+ (o :: Row Type)
58+ (m :: Type -> Type)
59+ (e :: Type) =
60+ GraphQLReqRes operation gql i o
61+ => IsSymbol gql
62+ => JSON.WriteForeign { | i }
63+ => JSON.ReadForeign { | o }
64+ => MonadAff m
65+ => MonadThrow e m
66+ => (NetworkErrorInfo -> e)
67+ -> (ParsingErrorInfo -> e)
68+ -> Gql operation
69+ -> Record i
70+ -> m { | o }
3571
36−graphQL :: Endpoint -> Array RequestHeader -> (forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type). GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => Gql operation -> Record i -> Aff { | o })
37−graphQL endpoint headers = graphQL' endpoint headers (error <<< AX.printError) (error <<< _.body)
72+type GraphQLClient =
73+ forall (operation :: GraphQL)
74+ (gql :: Symbol) (i :: Row Type) (o :: Row Type) (m :: Type -> Type) (e :: Type)
75+ . GraphQLClient' operation gql i o m e
76+
77+graphQL
78+ :: Endpoint
79+ -> Array RequestHeader
80+ -> ( forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type)
81+ . GraphQLReqRes operation gql i o
82+ => IsSymbol gql
83+ => JSON.WriteForeign { | i }
84+ => JSON.ReadForeign { | o }
85+ => Gql operation
86+ -> Record i
87+ -> Aff { | o }
88+ )
89+graphQL endpoint headers = graphQL'
90+ endpoint
91+ headers
92+ (error <<< AX.printError <<< _.error)
93+ (error <<< _.body <<< _.response)
3894
3995graphQL' :: Endpoint -> Array RequestHeader -> GraphQLClient
40−graphQL' endpoint headers = go
96+graphQL' endpoint headers' = go
4197 where
42− go :: forall (operation :: GraphQL) (gql :: Symbol) (i :: Row Type) (o :: Row Type) (m :: Type -> Type) (e :: Type). GraphQLReqRes operation gql i o => IsSymbol gql => JSON.WriteForeign { | i } => JSON.ReadForeign { | o } => MonadAff m => MonadThrow e m => MonadError e m => (AX.Error -> e) -> (AX.Response String -> e) ->Gql operation -> Record i -> m { | o }
98+ requestHeaders = headers' <> [ ContentType $ MediaType "application/json" ]
99+
100+ go
101+ :: forall (operation :: GraphQL) (gql :: Symbol)
102+ (i :: Row Type) (o :: Row Type) (m :: Type -> Type) (e :: Type)
103+ . GraphQLReqRes operation gql i o
104+ => IsSymbol gql
105+ => JSON.WriteForeign
106+ { | i }
107+ => JSON.ReadForeign { | o }
108+ => MonadAff m
109+ => MonadThrow e m
110+ => (NetworkErrorInfo -> e)
111+ -> (ParsingErrorInfo -> e)
112+ -> Gql operation
113+ -> Record i
114+ -> m { | o }
43115 go networkErrorF readErrorF _ variables = do
44116 let
45117 input =
46118 { variables
47− , query: String.replaceAll (String.Pattern "\n") (String.Replacement " ") (String.replaceAll (String.Pattern "\r\n") (String.Replacement " ") (reflectSymbol (Proxy :: Proxy gql)))
119+ , query: String.replaceAll (String.Pattern "\n")
120+ (String.Replacement " ")
121+ ( String.replaceAll
122+ (String.Pattern "\r\n")
123+ (String.Replacement " ")
124+ (reflectSymbol (Proxy :: Proxy gql))
125+ )
48126 }
127+ requestBody = JSON.writeJSON input
49128 res <-
50129 liftAff $ AX.request
51130 ( AX.defaultRequest
@@ -53,15 +132,23 @@ graphQL' endpoint headers = go
53132 , method = Left POST
54133 , responseFormat = ResponseFormat.string
55134 , content =
56− Just
57− (RequestBody.string (JSON.writeJSON input))
58− , headers = headers <> [ContentType $ MediaType "application/json"]
135+ Just
136+ (RequestBody.string requestBody)
137+ , headers = requestHeaders
59138 }
60139 )
61140 case res of
62− Left err -> do
141+ Left error -> do
63142 liftEffect $ Log.info "Request did not go through"
64− throwError (networkErrorF err)
143+ throwError (networkErrorF { endpoint, requestHeaders, error, requestBody })
65144 Right response -> case (JSON.readJSON response.body) of
66− Left _ -> throwError (readErrorF response)
145+ Left jsonParsingError -> throwError
146+ ( readErrorF
147+ { endpoint
148+ , requestHeaders
149+ , jsonParsingError
150+ , requestBody
151+ , response
152+ }
153+ )
67154 Right ({ data: d } :: { data :: { | o } }) -> pure d