import PocketBase from "pocketbase"; const url = process.env.NEXT_PUBLIC_POCKETBASE_URL || "http://127.0.0.1:8090"; const ADMIN_TOKEN_REFRESH_BUFFER_MS = 60_000; type CachedAdminAuth = { token: string; expiresAt: number; }; let cachedAdminAuth: CachedAdminAuth | null = null; function readJwtExpiryMs(token: string): number { const parts = token.split("."); if (parts.length < 2) return 0; try { const payload = JSON.parse( Buffer.from(parts[1], "base64url").toString("utf8"), ) as { exp?: unknown }; if (typeof payload.exp !== "number" || !Number.isFinite(payload.exp)) { return 0; } return payload.exp * 1000; } catch { return 0; } } function buildPocketBaseWithCachedAuth(): PocketBase | null { if ( !cachedAdminAuth || cachedAdminAuth.expiresAt <= Date.now() + ADMIN_TOKEN_REFRESH_BUFFER_MS ) { return null; } const pb = new PocketBase(url); // Disable auto-cancellation. The PB SDK's default behaviour is to // cancel every in-flight request whenever a new one starts — that // works fine for sequential UI calls but breaks any service that // fans out reads via Promise.all (e.g. `populateQuoteItemInsights` // fires 8 PB queries in parallel and the SDK aborts the first 7 the // moment the 8th starts). Safe for admin client: we don't have user // cancellation semantics, and the requests are idempotent. pb.autoCancellation(false); if (pb.authStore && typeof pb.authStore.save === "function") { pb.authStore.save(cachedAdminAuth.token); return pb; } return null; } export function clearAdminPocketBaseAuthCache(): void { cachedAdminAuth = null; } export async function getAdminPocketBase() { const email = process.env.PB_ADMIN_EMAIL; const password = process.env.PB_ADMIN_PASSWORD; if (!email || !password) { throw new Error("PB_ADMIN_EMAIL and PB_ADMIN_PASSWORD are required for server API operations."); } const cachedPb = buildPocketBaseWithCachedAuth(); if (cachedPb) return cachedPb; const pb = new PocketBase(url); // See buildPocketBaseWithCachedAuth — autoCancellation(false) so // Promise.all fan-outs (e.g. populateQuoteItemInsights) don't get // aborted mid-flight. pb.autoCancellation(false); const authData = await pb.collection("_superusers").authWithPassword(email, password); cachedAdminAuth = { token: authData.token, expiresAt: readJwtExpiryMs(authData.token), }; return pb; }