type PocketBaseClientOptions = { baseUrl: string; email: string; password: string; }; type PocketBaseListOptions = { collectionName: string; filter?: string; }; type AuthResponse = { token: string; }; type RecordListResponse = { items: TRecord[]; }; export function createPocketBaseClient(options: PocketBaseClientOptions) { let cachedToken: string | null = null; async function authenticate() { if (cachedToken) return cachedToken; const response = await fetch( `${options.baseUrl}/api/collections/_superusers/auth-with-password`, { method: "POST", headers: { "content-type": "application/json", }, body: JSON.stringify({ identity: options.email, password: options.password, }), }, ); if (!response.ok) { throw new Error(`PocketBase auth failed with status ${response.status}`); } const payload = await response.json() as AuthResponse; cachedToken = payload.token; return cachedToken; } return { async listRecords(input: PocketBaseListOptions) { const token = await authenticate(); const url = new URL( `${options.baseUrl}/api/collections/${input.collectionName}/records`, ); if (input.filter) { url.searchParams.set("filter", input.filter); } const response = await fetch(url, { headers: { Authorization: `Bearer ${token}`, }, }); if (!response.ok) { throw new Error(`PocketBase list failed with status ${response.status}`); } const payload = await response.json() as RecordListResponse; return payload.items; }, }; }