diff --git a/src/shared/api/api.ts b/src/shared/api/api.ts new file mode 100644 index 0000000..1b440d6 --- /dev/null +++ b/src/shared/api/api.ts @@ -0,0 +1,61 @@ +import type { ApiResponse } from '$shared/types/common'; + +export class ApiError extends Error { + constructor( + public status: number, + message: string, + public response?: Response, + ) { + super(message); + this.name = 'ApiError'; + } +} + +async function request( + url: string, + options?: RequestInit, +): Promise> { + const response = await fetch(url, { + headers: { + 'Content-Type': 'application/json', + ...options?.headers, + }, + ...options, + }); + + if (!response.ok) { + throw new ApiError( + response.status, + `Request failed: ${response.statusText}`, + response, + ); + } + + const data = await response.json() as T; + + return { + data, + status: response.status, + }; +} + +export const api = { + get: (url: string, options?: RequestInit) => request(url, { ...options, method: 'GET' }), + + post: (url: string, body?: unknown, options?: RequestInit) => + request(url, { + ...options, + method: 'POST', + body: JSON.stringify(body), + }), + + put: (url: string, body?: unknown, options?: RequestInit) => + request(url, { + ...options, + method: 'PUT', + body: JSON.stringify(body), + }), + + delete: (url: string, options?: RequestInit) => + request(url, { ...options, method: 'DELETE' }), +};