Skip to content

Commit 4d70e38

Browse files
committed
Extract the api to a new file
1 parent 2152718 commit 4d70e38

File tree

13 files changed

+116
-106
lines changed

13 files changed

+116
-106
lines changed

ui/frontend/.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ module.exports = {
6767
'Header.tsx',
6868
'PopButton.tsx',
6969
'Stdin.tsx',
70+
'api.ts',
7071
'compileActions.ts',
7172
'editor/AceEditor.tsx',
7273
'editor/SimpleEditor.tsx',

ui/frontend/.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ node_modules
1818
!Header.tsx
1919
!PopButton.tsx
2020
!Stdin.tsx
21+
!api.ts
2122
!compileActions.ts
2223
!editor/AceEditor.tsx
2324
!editor/SimpleEditor.tsx

ui/frontend/actions.ts

Lines changed: 0 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import fetch from 'isomorphic-fetch';
21
import { ThunkAction as ReduxThunkAction, AnyAction } from '@reduxjs/toolkit';
32

43
import {
@@ -35,21 +34,6 @@ import { performCompileToLlvmIrOnly } from './reducers/output/llvmIr';
3534
import { performCompileToMirOnly } from './reducers/output/mir';
3635
import { performCompileToWasmOnly } from './reducers/output/wasm';
3736

38-
export const routes = {
39-
compile: '/compile',
40-
execute: '/execute',
41-
format: '/format',
42-
clippy: '/clippy',
43-
miri: '/miri',
44-
macroExpansion: '/macro-expansion',
45-
meta: {
46-
crates: '/meta/crates',
47-
versions: '/meta/versions',
48-
gistSave: '/meta/gist',
49-
gistLoad: '/meta/gist/id',
50-
},
51-
};
52-
5337
export type ThunkAction<T = void> = ReduxThunkAction<T, State, {}, Action>;
5438
export type SimpleThunkAction<T = void> = ReduxThunkAction<T, State, {}, AnyAction>;
5539

@@ -148,87 +132,6 @@ export const reExecuteWithBacktrace = (): ThunkAction => dispatch => {
148132
dispatch(performExecuteOnly());
149133
};
150134

151-
type FetchArg = Parameters<typeof fetch>[0];
152-
153-
export function jsonGet(url: FetchArg): Promise<unknown> {
154-
return fetchJson(url, {
155-
method: 'get',
156-
});
157-
}
158-
159-
export function jsonPost(url: FetchArg, body: Record<string, any>): Promise<unknown> {
160-
return fetchJson(url, {
161-
method: 'post',
162-
body: JSON.stringify(body),
163-
});
164-
}
165-
166-
async function fetchJson(url: FetchArg, args: RequestInit) {
167-
const headers = new Headers(args.headers);
168-
headers.set('Content-Type', 'application/json');
169-
170-
let response;
171-
try {
172-
response = await fetch(url, { ...args, headers });
173-
} catch (networkError) {
174-
// e.g. server unreachable
175-
if (networkError instanceof Error) {
176-
throw ({
177-
error: `Network error: ${networkError.toString()}`,
178-
});
179-
} else {
180-
throw ({
181-
error: 'Unknown error while fetching JSON',
182-
});
183-
}
184-
}
185-
186-
let body;
187-
try {
188-
body = await response.json();
189-
} catch (convertError) {
190-
if (convertError instanceof Error) {
191-
throw ({
192-
error: `Response was not JSON: ${convertError.toString()}`,
193-
});
194-
} else {
195-
throw ({
196-
error: 'Unknown error while converting JSON',
197-
});
198-
}
199-
}
200-
201-
if (response.ok) {
202-
// HTTP 2xx
203-
return body;
204-
} else {
205-
// HTTP 4xx, 5xx (e.g. malformed JSON request)
206-
throw body;
207-
}
208-
}
209-
210-
// We made some strange decisions with how the `fetchJson` function
211-
// communicates errors, so we untwist those here to fit better with
212-
// redux-toolkit's ideas.
213-
export const adaptFetchError = async <R>(cb: () => Promise<R>): Promise<R> => {
214-
let result;
215-
216-
try {
217-
result = await cb();
218-
} catch (e) {
219-
if (e && typeof e === 'object' && 'error' in e && typeof e.error === 'string') {
220-
throw new Error(e.error);
221-
} else {
222-
throw new Error('An unknown error occurred');
223-
}
224-
}
225-
226-
if (result && typeof result === 'object' && 'error' in result && typeof result.error === 'string') {
227-
throw new Error(result.error);
228-
}
229-
230-
return result;
231-
}
232135

233136
function performAutoOnly(): ThunkAction {
234137
return function(dispatch, getState) {

ui/frontend/api.ts

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import fetch from 'isomorphic-fetch';
2+
3+
export const routes = {
4+
compile: '/compile',
5+
execute: '/execute',
6+
format: '/format',
7+
clippy: '/clippy',
8+
miri: '/miri',
9+
macroExpansion: '/macro-expansion',
10+
meta: {
11+
crates: '/meta/crates',
12+
versions: '/meta/versions',
13+
gistSave: '/meta/gist',
14+
gistLoad: '/meta/gist/id',
15+
},
16+
};
17+
18+
type FetchArg = Parameters<typeof fetch>[0];
19+
20+
export function jsonGet(url: FetchArg): Promise<unknown> {
21+
return fetchJson(url, {
22+
method: 'get',
23+
});
24+
}
25+
26+
export function jsonPost(url: FetchArg, body: Record<string, any>): Promise<unknown> {
27+
return fetchJson(url, {
28+
method: 'post',
29+
body: JSON.stringify(body),
30+
});
31+
}
32+
33+
async function fetchJson(url: FetchArg, args: RequestInit) {
34+
const headers = new Headers(args.headers);
35+
headers.set('Content-Type', 'application/json');
36+
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+
}
67+
68+
if (response.ok) {
69+
// HTTP 2xx
70+
return body;
71+
} else {
72+
// HTTP 4xx, 5xx (e.g. malformed JSON request)
73+
throw body;
74+
}
75+
}
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+
};

ui/frontend/compileActions.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit';
22
import * as z from 'zod';
33

4-
import { SimpleThunkAction, adaptFetchError, jsonPost, routes } from './actions';
4+
import { SimpleThunkAction } from './actions';
5+
import { adaptFetchError, jsonPost, routes } from './api';
56
import { compileRequestPayloadSelector } from './selectors';
67

78
interface CompileRequestBody {

ui/frontend/reducers/crates.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
22
import { sortBy } from 'lodash-es';
33
import * as z from 'zod';
44

5-
import { adaptFetchError, jsonGet, routes } from '../actions';
5+
import { adaptFetchError, jsonGet, routes } from '../api';
66
import { Crate } from '../types';
77

88
const sliceName = 'crates';

ui/frontend/reducers/output/clippy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
22
import * as z from 'zod';
33

4-
import { adaptFetchError, jsonPost, routes } from '../../actions';
4+
import { adaptFetchError, jsonPost, routes } from '../../api';
55
import { clippyRequestSelector } from '../../selectors';
66
import RootState from '../../state';
77

ui/frontend/reducers/output/execute.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import { AnyAction, Draft, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
22
import * as z from 'zod';
33

4-
import { SimpleThunkAction, adaptFetchError, jsonPost, routes } from '../../actions';
4+
import { SimpleThunkAction } from '../../actions';
5+
import { adaptFetchError, jsonPost, routes } from '../../api';
56
import { executeRequestPayloadSelector, executeViaWebsocketSelector } from '../../selectors';
67
import { Channel, Edition, Mode } from '../../types';
78
import {

ui/frontend/reducers/output/format.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';
22
import * as z from 'zod';
33

4-
import { adaptFetchError, jsonPost, routes } from '../../actions';
4+
import { adaptFetchError, jsonPost, routes } from '../../api';
55
import { formatRequestSelector } from '../../selectors';
66
import RootState from '../../state';
77

ui/frontend/reducers/output/gist.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Draft, PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
22
import * as z from 'zod';
33

4-
import { adaptFetchError, jsonGet, jsonPost, routes } from '../../actions';
4+
import { adaptFetchError, jsonGet, jsonPost, routes } from '../../api';
55
import { baseUrlSelector, codeSelector } from '../../selectors';
66
import RootState from '../../state';
77
import { Channel, Edition, Mode } from '../../types';

0 commit comments

Comments
 (0)