82 lines
2.4 KiB
TypeScript
82 lines
2.4 KiB
TypeScript
import { BASE_URL, API_BASE } from './constants';
|
|
import { siteId } from './settings';
|
|
import { StaticStore } from './static_store';
|
|
import { getCookie } from './cookies';
|
|
|
|
export type FetcherMethod = 'get' | 'post' | 'put' | 'patch' | 'delete' | 'head';
|
|
const methods: FetcherMethod[] = ['get', 'post', 'put', 'patch', 'delete', 'head'];
|
|
|
|
type FetcherInit =
|
|
| string
|
|
| {
|
|
url: string;
|
|
body?: string | object | Blob | ArrayBuffer;
|
|
overriddenApiBase?: string;
|
|
withCredentials?: boolean;
|
|
};
|
|
|
|
type FetcherObject = { [K in FetcherMethod]: <T = unknown>(data: FetcherInit) => Promise<T> };
|
|
|
|
const fetcher = methods.reduce<Partial<FetcherObject>>((acc, method) => {
|
|
acc[method] = <T = unknown>(data: FetcherInit): Promise<T> => {
|
|
const { url, body = undefined, withCredentials = false, overriddenApiBase = API_BASE } =
|
|
typeof data === 'string' ? { url: data } : data;
|
|
const basename = `${BASE_URL}${overriddenApiBase}`;
|
|
|
|
const headers = new Headers({
|
|
Accept: 'application/json',
|
|
'Content-Type': 'application/json',
|
|
'X-XSRF-TOKEN': getCookie('XSRF-TOKEN') || '',
|
|
});
|
|
|
|
let rurl = `${basename}${url}`;
|
|
|
|
const parameters: RequestInit = {
|
|
method,
|
|
headers,
|
|
mode: 'cors',
|
|
credentials: withCredentials ? 'include' : 'omit',
|
|
};
|
|
|
|
if (body) {
|
|
if (typeof body === 'object') {
|
|
parameters.body = JSON.stringify(body);
|
|
} else {
|
|
parameters.body = body;
|
|
}
|
|
}
|
|
|
|
if (siteId && method !== 'post' && !rurl.includes('?site=') && !rurl.includes('&site=')) {
|
|
rurl += (rurl.includes('?') ? '&' : '?') + `site=${siteId}`;
|
|
}
|
|
|
|
return fetch(rurl, parameters).then(res => {
|
|
const date = (res.headers.has('date') && res.headers.get('date')) || '';
|
|
const timestamp = isNaN(Date.parse(date)) ? 0 : Date.parse(date);
|
|
const timeDiff = (new Date().getTime() - timestamp) / 1000;
|
|
StaticStore.serverClientTimeDiff = timeDiff;
|
|
|
|
if (res.status >= 400) {
|
|
return res.text().then(text => {
|
|
let err;
|
|
try {
|
|
err = JSON.parse(text);
|
|
} catch (e) {
|
|
throw text;
|
|
}
|
|
throw err;
|
|
});
|
|
}
|
|
|
|
if (res.headers.has('Content-Type') && res.headers.get('Content-Type')!.indexOf('application/json') === 0) {
|
|
return res.json();
|
|
}
|
|
|
|
return res.text();
|
|
});
|
|
};
|
|
return acc;
|
|
}, {}) as FetcherObject;
|
|
|
|
export default fetcher;
|