Add authenticated fetch wrapper for the todos API
This commit is contained in:
56
frontend/src/lib/api.ts
Normal file
56
frontend/src/lib/api.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { supabase } from './supabase';
|
||||||
|
|
||||||
|
const API_URL = import.meta.env.VITE_API_URL;
|
||||||
|
if (!API_URL) throw new Error('Missing VITE_API_URL');
|
||||||
|
|
||||||
|
export type Todo = {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
completed: boolean;
|
||||||
|
createdAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function authedFetch(path: string, init: RequestInit = {}): Promise<Response> {
|
||||||
|
const { data } = await supabase.auth.getSession();
|
||||||
|
const token = data.session?.access_token;
|
||||||
|
if (!token) throw new Error('Not signed in');
|
||||||
|
|
||||||
|
const headers = new Headers(init.headers);
|
||||||
|
headers.set('Authorization', `Bearer ${token}`);
|
||||||
|
if (init.body && !headers.has('Content-Type')) headers.set('Content-Type', 'application/json');
|
||||||
|
|
||||||
|
return fetch(`${API_URL}${path}`, { ...init, headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
async function assertOk(res: Response): Promise<Response> {
|
||||||
|
if (!res.ok) {
|
||||||
|
const text = await res.text().catch(() => '');
|
||||||
|
throw new Error(`API ${res.status}: ${text || res.statusText}`);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const api = {
|
||||||
|
async list(): Promise<Todo[]> {
|
||||||
|
const res = await assertOk(await authedFetch('/api/todos'));
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
async create(title: string): Promise<Todo> {
|
||||||
|
const res = await assertOk(
|
||||||
|
await authedFetch('/api/todos', { method: 'POST', body: JSON.stringify({ title }) })
|
||||||
|
);
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
async setCompleted(id: number, completed: boolean): Promise<Todo> {
|
||||||
|
const res = await assertOk(
|
||||||
|
await authedFetch(`/api/todos/${id}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: JSON.stringify({ completed })
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return res.json();
|
||||||
|
},
|
||||||
|
async remove(id: number): Promise<void> {
|
||||||
|
await assertOk(await authedFetch(`/api/todos/${id}`, { method: 'DELETE' }));
|
||||||
|
}
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user