import { baseUrl } from '../integration/setup'; /** * Minimal fetch wrapper bound to the test server with a per-instance * cookie jar, so each client represents one browser session. */ export class ApiClient { private readonly cookies = new Map(); constructor(private readonly base: string) {} async request(path: string, init: RequestInit = {}): Promise { const headers = new Headers(init.headers); if (this.cookies.size > 0) { headers.set( 'cookie', [...this.cookies].map(([name, value]) => `${name}=${value}`).join('; ') ); } const res = await fetch(`${this.base}${path}`, { ...init, headers }); for (const cookie of res.headers.getSetCookie()) { const [pair, ...attributes] = cookie.split(';'); const separator = pair.indexOf('='); const name = pair.slice(0, separator).trim(); const value = pair.slice(separator + 1).trim(); const expired = attributes.some((attr) => /^expires=Thu, 01 Jan 1970/i.test(attr.trim()) ); if (value === '' || expired) { this.cookies.delete(name); } else { this.cookies.set(name, value); } } return res; } get(path: string) { return this.request(path); } post(path: string, body?: unknown) { const init: RequestInit = body instanceof FormData ? { method: 'POST', body } : { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body ?? {}) }; return this.request(path, init); } async register(email: string, name: string, password: string) { return this.post('/api/auth/register', { email, name, password }); } async login(email: string, password: string) { return this.post('/api/auth/login', { email, password }); } } export const api = new ApiClient(baseUrl); export function newClient() { return new ApiClient(baseUrl); }