80 lines
1.8 KiB
TypeScript
80 lines
1.8 KiB
TypeScript
export class ApiError extends Error {
|
|
readonly status: number;
|
|
|
|
constructor(message: string, status: number) {
|
|
super(message);
|
|
this.name = "ApiError";
|
|
this.status = status;
|
|
}
|
|
}
|
|
|
|
type RequestInitWithJson = RequestInit & {
|
|
json?: unknown;
|
|
};
|
|
|
|
async function request<TResponse>(
|
|
input: string,
|
|
init: RequestInitWithJson = {},
|
|
): Promise<TResponse> {
|
|
const headers = new Headers(init.headers);
|
|
const body =
|
|
init.json === undefined ? init.body : JSON.stringify(init.json, null, 2);
|
|
|
|
if (init.json !== undefined) {
|
|
headers.set("Content-Type", "application/json");
|
|
}
|
|
|
|
const response = await fetch(input, {
|
|
...init,
|
|
headers,
|
|
body,
|
|
});
|
|
|
|
if (!response.ok) {
|
|
let message = `${response.status} ${response.statusText}`;
|
|
|
|
try {
|
|
const errorPayload = (await response.json()) as {
|
|
error?: { message?: string };
|
|
};
|
|
message = errorPayload.error?.message ?? message;
|
|
} catch {
|
|
message = `${response.status} ${response.statusText}`;
|
|
}
|
|
|
|
throw new ApiError(message, response.status);
|
|
}
|
|
|
|
const contentType = response.headers.get("Content-Type") ?? "";
|
|
if (contentType.includes("application/yaml")) {
|
|
return (await response.text()) as TResponse;
|
|
}
|
|
|
|
return (await response.json()) as TResponse;
|
|
}
|
|
|
|
export function getJson<TResponse>(input: string) {
|
|
return request<TResponse>(input);
|
|
}
|
|
|
|
export function getText(input: string) {
|
|
return request<string>(input);
|
|
}
|
|
|
|
export function postJson<TResponse>(input: string, json?: unknown) {
|
|
return request<TResponse>(input, {
|
|
method: "POST",
|
|
json,
|
|
});
|
|
}
|
|
|
|
export function postText<TResponse>(input: string, text: string) {
|
|
return request<TResponse>(input, {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/yaml",
|
|
},
|
|
body: text,
|
|
});
|
|
}
|