|
1 | 1 | import fetch from 'isomorphic-fetch'; |
| 2 | +import * as z from 'zod'; |
2 | 3 |
|
3 | 4 | export const routes = { |
4 | 5 | compile: '/compile', |
@@ -30,74 +31,24 @@ export function jsonPost(url: FetchArg, body: Record<string, any>): Promise<unkn |
30 | 31 | }); |
31 | 32 | } |
32 | 33 |
|
| 34 | +const ErrorResponse = z.object({ |
| 35 | + error: z.string(), |
| 36 | +}); |
| 37 | +type ErrorResponse = z.infer<typeof ErrorResponse>; |
| 38 | + |
33 | 39 | async function fetchJson(url: FetchArg, args: RequestInit) { |
34 | 40 | const headers = new Headers(args.headers); |
35 | 41 | headers.set('Content-Type', 'application/json'); |
36 | 42 |
|
37 | | - let response; |
38 | | - try { |
39 | | - response = await fetch(url, { ...args, headers }); |
40 | | - } catch (networkError) { |
41 | | - // e.g. server unreachable |
42 | | - if (networkError instanceof Error) { |
43 | | - throw { |
44 | | - error: `Network error: ${networkError.toString()}`, |
45 | | - }; |
46 | | - } else { |
47 | | - throw { |
48 | | - error: 'Unknown error while fetching JSON', |
49 | | - }; |
50 | | - } |
51 | | - } |
52 | | - |
53 | | - let body; |
54 | | - try { |
55 | | - body = await response.json(); |
56 | | - } catch (convertError) { |
57 | | - if (convertError instanceof Error) { |
58 | | - throw { |
59 | | - error: `Response was not JSON: ${convertError.toString()}`, |
60 | | - }; |
61 | | - } else { |
62 | | - throw { |
63 | | - error: 'Unknown error while converting JSON', |
64 | | - }; |
65 | | - } |
66 | | - } |
| 43 | + const response = await fetch(url, { ...args, headers }); |
| 44 | + const body = await response.json(); |
67 | 45 |
|
68 | 46 | if (response.ok) { |
69 | 47 | // HTTP 2xx |
70 | 48 | return body; |
71 | 49 | } else { |
72 | 50 | // HTTP 4xx, 5xx (e.g. malformed JSON request) |
73 | | - throw body; |
| 51 | + const error = await ErrorResponse.parseAsync(body); |
| 52 | + throw new Error(`The server reported an error: ${error.error}`); |
74 | 53 | } |
75 | 54 | } |
76 | | - |
77 | | -// We made some strange decisions with how the `fetchJson` function |
78 | | -// communicates errors, so we untwist those here to fit better with |
79 | | -// redux-toolkit's ideas. |
80 | | -export const adaptFetchError = async <R>(cb: () => Promise<R>): Promise<R> => { |
81 | | - let result; |
82 | | - |
83 | | - try { |
84 | | - result = await cb(); |
85 | | - } catch (e) { |
86 | | - if (e && typeof e === 'object' && 'error' in e && typeof e.error === 'string') { |
87 | | - throw new Error(e.error); |
88 | | - } else { |
89 | | - throw new Error('An unknown error occurred'); |
90 | | - } |
91 | | - } |
92 | | - |
93 | | - if ( |
94 | | - result && |
95 | | - typeof result === 'object' && |
96 | | - 'error' in result && |
97 | | - typeof result.error === 'string' |
98 | | - ) { |
99 | | - throw new Error(result.error); |
100 | | - } |
101 | | - |
102 | | - return result; |
103 | | -}; |
0 commit comments