48 lines
1.6 KiB
JavaScript
48 lines
1.6 KiB
JavaScript
export class ApiError extends Error {
|
|||
|
|
status;
|
||
|
|
constructor(status, message) {
|
||
|
|
super(message);
|
||
|
|
this.status = status;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
export async function request(method, path, opts = {}) {
|
||
|
|
const pathParams = (opts.path ?? {});
|
||
|
|
let url = path.replace(/\{(\w+)\}/g, (_, key) => {
|
||
|
|
const value = pathParams[key];
|
||
|
|
if (value === undefined) {
|
||
|
|
throw new Error(`missing path parameter ${key} for ${path}`);
|
||
|
|
}
|
||
|
|
return encodeURIComponent(String(value));
|
||
|
|
});
|
||
|
|
const query = new URLSearchParams();
|
||
|
|
for (const [key, value] of Object.entries((opts.query ?? {}))) {
|
||
|
|
if (value !== undefined) {
|
||
|
|
query.set(key, String(value));
|
||
|
|
}
|
||
|
|
}
|
||
|
|
if (query.size > 0) {
|
||
|
|
url += `?${query}`;
|
||
|
|
}
|
||
|
|
const init = { method: method.toUpperCase() };
|
||
|
|
if (opts.body !== undefined) {
|
||
|
|
init.headers = { "Content-Type": "application/json" };
|
||
|
|
init.body = JSON.stringify(opts.body);
|
||
|
|
}
|
||
|
|
const res = await fetch(url, init);
|
||
|
|
const data = await res.json();
|
||
|
|
if (!res.ok) {
|
||
|
|
throw new ApiError(res.status, data.message);
|
||
|
|
}
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
export const get = (path, opts) => request("get", path, opts);
|
||
|
|
export const post = (path, opts) => request("post", path, opts);
|
||
|
|
export const put = (path, opts) => request("put", path, opts);
|
||
|
|
export function subscribe(after, onEvent, onState) {
|
||
|
|
const source = new EventSource(`/api/events?after=${after}`);
|
||
|
|
source.onopen = () => onState(true);
|
||
|
|
source.onerror = () => onState(false);
|
||
|
|
source.onmessage = (msg) => onEvent(JSON.parse(msg.data));
|
||
|
|
return source;
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=api.js.map
|