MCPcopy Create free account
hub / github.com/CICCADA-CORP/SoundTime / apiFetch

Function apiFetch

frontend/src/lib/api.ts:56–98  ·  view source on GitHub ↗
(
  path: string,
  options: RequestInit = {}
)

Source from the content-addressed store, hash-verified

54}
55
56export async function apiFetch<T = unknown>(
57 path: string,
58 options: RequestInit = {}
59): Promise<T> {
60 const headers = new Headers(options.headers ?? {});
61 const token = getAccessToken();
62 if (token) {
63 headers.set("Authorization", `Bearer ${token}`);
64 }
65
66 if (
67 !headers.has("Content-Type") &&
68 !(options.body instanceof FormData)
69 ) {
70 headers.set("Content-Type", "application/json");
71 }
72
73 let res = await fetch(`${API_BASE}${path}`, { ...options, headers });
74
75 // Auto-refresh on 401
76 if (res.status === 401 && token) {
77 const refreshed = await refreshAccessToken();
78 if (refreshed) {
79 const newToken = getAccessToken();
80 if (newToken) {
81 headers.set("Authorization", `Bearer ${newToken}`);
82 }
83 res = await fetch(`${API_BASE}${path}`, { ...options, headers });
84 }
85 }
86
87 if (!res.ok) {
88 const err: ApiError = await res.json().catch(() => ({
89 error: `HTTP ${res.status}`,
90 }));
91 throw new Error(err.error);
92 }
93
94 if (res.status === 204) return undefined as T;
95 const text = await res.text();
96 if (!text) return undefined as T;
97 return JSON.parse(text);
98}
99
100export const api = {
101 get: <T = unknown>(path: string) => apiFetch<T>(path),

Callers 4

api.test.tsFile · 0.90
deleteAccountFunction · 0.90
updatePasswordFunction · 0.90
api.tsFile · 0.85

Calls 3

getAccessTokenFunction · 0.85
refreshAccessTokenFunction · 0.85
parseMethod · 0.80

Tested by

no test coverage detected