mirror of
https://github.com/tdurieux/anonymous_github.git
synced 2026-09-12 13:48:58 +02:00
53 lines
2.6 KiB
JavaScript
53 lines
2.6 KiB
JavaScript
// Keep response metadata alongside parsed data for the existing API consumers.
|
|
export function createHttp(fetcher = (...args) => fetch(...args)) {
|
|
async function request(method, url, data, options = {}) {
|
|
const target = new URL(url, window.location.href);
|
|
for (const [key, value] of Object.entries(options.params || {})) {
|
|
if (value == null) continue;
|
|
for (const item of Array.isArray(value) ? value : [value]) target.searchParams.append(key, typeof item === "object" ? JSON.stringify(item) : item);
|
|
}
|
|
const controller = new AbortController();
|
|
let timer;
|
|
if (options.timeout?.then) options.timeout.then(() => controller.abort());
|
|
else if (options.timeout) timer = setTimeout(() => controller.abort(), options.timeout);
|
|
try {
|
|
const headers = { Accept: "application/json, text/plain, */*", ...options.headers };
|
|
const csrf = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]*)/);
|
|
if (csrf && target.origin === window.location.origin) headers["X-XSRF-TOKEN"] = decodeURIComponent(csrf[1]);
|
|
let body;
|
|
if (data !== undefined) {
|
|
if (data instanceof FormData) body = data;
|
|
else { headers["Content-Type"] ||= "application/json;charset=utf-8"; body = JSON.stringify(data); }
|
|
}
|
|
const response = await fetcher(target.href, { method, headers, body, credentials: "same-origin", signal: controller.signal });
|
|
const raw = await response.text();
|
|
let result = raw;
|
|
if (options.transformResponse) result = options.transformResponse(raw);
|
|
else if (raw && (/json/i.test(response.headers.get("content-type") || "") || /^[\[{]/.test(raw.trim()))) {
|
|
try { result = JSON.parse(raw); } catch { /* File content may start with a brace. */ }
|
|
}
|
|
const value = { data: result, status: response.status, headers: name => response.headers.get(name) };
|
|
if (!response.ok) throw value;
|
|
return value;
|
|
} catch (error) {
|
|
if (error.name === "AbortError") throw { status: -1, data: null };
|
|
throw error;
|
|
} finally { clearTimeout(timer); }
|
|
}
|
|
const http = {};
|
|
for (const method of ["get", "delete", "head"]) http[method] = (url, options) => request(method.toUpperCase(), url, undefined, options);
|
|
for (const method of ["post", "put", "patch"]) http[method] = (url, data, options) => request(method.toUpperCase(), url, data, options);
|
|
return http;
|
|
}
|
|
|
|
export const promises = {
|
|
resolve: value => Promise.resolve(value),
|
|
reject: error => Promise.reject(error),
|
|
all: values => Promise.all(values),
|
|
defer() {
|
|
let resolve, reject;
|
|
const promise = new Promise((yes, no) => { resolve = yes; reject = no; });
|
|
return { promise, resolve, reject };
|
|
},
|
|
};
|