Files
remark42/web/app/common/fetcher.ts
T

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;