@@ -5,6 +5,8 @@ module Yoga.Fetch.Om.ParseResponse
55 , parseSuccessRL
66 , class ParseErrorRL
77 , parseErrorRL
8+ , class ParseResponseBody
9+ , parseResponseBody
810 ) where
911
1012import Prelude
@@ -36,6 +38,15 @@ import Yoga.Om.Error (Exception)
3638import Yoga.Om.Strom (Strom)
3739import Yoga.Om.Strom.WebStream as WebStream
3840
41+class ParseResponseBody (body :: Type) where
42+ parseResponseBody :: String -> Either String body
43+
44+instance ParseResponseBody String where
45+ parseResponseBody = Right
46+
47+else instance ReadForeign body => ParseResponseBody body where
48+ parseResponseBody = withStringErrors <<< readJSON
49+
3950class ParseResponse (errorRow :: Row Type) (successRow :: Row Type) where
4051 parseResponse :: FetchResponse.Response -> Om {} errorRow (Variant successRow)
4152
@@ -50,11 +61,9 @@ instance
5061 let status = Fetch.status fetchResp
5162 if status >= 200 && status < 300 then
5263 parseSuccessRL (Proxy :: _ successRL) status fetchResp # toOm
53โ else if status >= 400 then do
64+ else do
5465 errorText <- Promise.toAffE (Fetch.text fetchResp) # toOm
5566 parseErrorRL (Proxy :: _ errorRL) (Proxy :: _ errorRow) status errorText
56โ else
57โ throwError (Variant.inj (Proxy :: _ "exception") (Exception.error ("Unexpected HTTP status code: " <> show status)))
5867
5968class ParseSuccessRL (rl :: RowList Type) (successRow :: Row Type) | rl -> successRow where
6069 parseSuccessRL :: Proxy rl -> Int -> FetchResponse.Response -> Aff (Variant successRow)
@@ -100,7 +109,7 @@ else instance
100109else instance
101110 ( IsSymbol label
102111 , StatusCodeMap label
103โ , ReadForeign body
112+ , ParseResponseBody body
104113 , Row.Cons label body tailRow successRow
105114 , Row.Lacks label tailRow
106115 , ParseSuccessRL tailRL successRow
@@ -110,7 +119,7 @@ else instance
110119 let StatusCode expected = statusCodeFor (Proxy :: _ label)
111120 if actualStatus == expected then do
112121 jsonText <- liftEffect (Fetch.text fetchResp) >>= Promise.toAff
113โ case withStringErrors (readJSON jsonText) of
122+ case parseResponseBody jsonText of
114123 Left errs -> Aff.throwError (Exception.error ("Failed to parse response (status " <> show actualStatus <> "):\n" <> errs))
115124 Right parsed -> pure (Variant.inj (Proxy :: _ label) parsed)
116125 else
@@ -148,7 +157,21 @@ else instance
148157else instance
149158 ( IsSymbol label
150159 , StatusCodeMap label
151โ , ReadForeign body
160+ , Row.Cons label Unit tailRow errorRow
161+ , Row.Lacks label tailRow
162+ , Row.Cons label Unit tailExc (Exception errorRow)
163+ , ParseErrorRL tailRL errorRow
164+ ) =>
165+ ParseErrorRL (RL.Cons label Unit tailRL) errorRow where
166+ parseErrorRL _ errorProxy actualStatus jsonText = do
167+ let StatusCode expected = statusCodeFor (Proxy :: _ label)
168+ if actualStatus == expected then throwError (Variant.inj (Proxy :: _ label) unit)
169+ else parseErrorRL (Proxy :: _ tailRL) errorProxy actualStatus jsonText
170+
171+else instance
172+ ( IsSymbol label
173+ , StatusCodeMap label
174+ , ParseResponseBody body
152175 , Row.Cons label body tailRow errorRow
153176 , Row.Lacks label tailRow
154177 , Row.Cons label body tailExc (Exception errorRow)
@@ -157,7 +180,7 @@ else instance
157180 ParseErrorRL (RL.Cons label body tailRL) errorRow where
158181 parseErrorRL _ errorProxy actualStatus jsonText = do
159182 let StatusCode expected = statusCodeFor (Proxy :: _ label)
160โ if actualStatus == expected then case withStringErrors (readJSON jsonText) of
183+ if actualStatus == expected then case parseResponseBody jsonText of
161184 Left errs -> throwError (Variant.inj (Proxy :: _ "exception") (Exception.error ("Failed to parse error response (status " <> show actualStatus <> "):\n" <> errs)))
162185 Right parsed -> throwError (Variant.inj (Proxy :: _ label) parsed)
163186 else