-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapiClient.ts
More file actions
82 lines (62 loc) · 1.88 KB
/
Copy pathapiClient.ts
File metadata and controls
82 lines (62 loc) · 1.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
import type { ApiErrorResponse } from '../types/api'
const API_BASE_URL =
import.meta.env.VITE_API_BASE_URL ?? 'https://quotematic.davlos.es'
type QueryParams = Record<string, string | number | boolean | null | undefined>
type ApiClientOptions = Omit<RequestInit, 'body'> & {
body?: unknown
query?: QueryParams
}
export class ApiError extends Error {
status: number
code?: string
constructor(message: string, status: number, code?: string) {
super(message)
this.name = 'ApiError'
this.status = status
this.code = code
}
}
function buildUrl(path: string, query?: QueryParams) {
const url = new URL(path, API_BASE_URL)
if (query) {
Object.entries(query).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
url.searchParams.set(key, String(value))
}
})
}
return url.toString()
}
async function parseResponse<T>(response: Response): Promise<T> {
const text = await response.text()
if (!text) {
return null as T
}
return JSON.parse(text) as T
}
export async function apiClient<T>(
path: string,
options: ApiClientOptions = {},
): Promise<T> {
const { body, query, headers, ...fetchOptions } = options
const requestHeaders = new Headers(headers)
if (body !== undefined && !requestHeaders.has('Content-Type')) {
requestHeaders.set('Content-Type', 'application/json')
}
const response = await fetch(buildUrl(path, query), {
...fetchOptions,
credentials: 'include',
headers: requestHeaders,
body: body !== undefined ? JSON.stringify(body) : undefined,
})
const data = await parseResponse<T | ApiErrorResponse>(response)
if (!response.ok) {
const errorData = data as ApiErrorResponse
throw new ApiError(
errorData.message ?? errorData.error ?? 'Error en la petición',
response.status,
errorData.code,
)
}
return data as T
}