// ABOUTME: PocketBase client initialization and authentication utilities. // ABOUTME: Provides typed access to the PocketBase backend for auth and data. import type { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies"; import PocketBase, { type RecordModel } from "pocketbase"; import type { OverrideType, User } from "@/types"; const POCKETBASE_URL = process.env.POCKETBASE_URL || "http://localhost:8090"; /** * Singleton PocketBase client for client-side usage. * For server-side, use createPocketBaseClient() to get a fresh instance. */ export const pb = new PocketBase(POCKETBASE_URL); // Disable auto-cancellation for server-side usage pb.autoCancellation(false); /** * Creates a new PocketBase client instance. * Use this in server components and API routes to get a fresh client * that can be loaded with request-specific auth. */ export function createPocketBaseClient(): PocketBase { const client = new PocketBase(POCKETBASE_URL); client.autoCancellation(false); return client; } /** * Checks if the PocketBase client has a valid authenticated session. */ export function isAuthenticated(pbClient: PocketBase): boolean { return pbClient.authStore.isValid; } /** * Gets the current authenticated user from the PocketBase auth store. * Returns null if not authenticated or if the model is not available. */ export function getCurrentUser(pbClient: PocketBase): User | null { if (!pbClient.authStore.isValid || !pbClient.authStore.model) { return null; } return mapRecordToUser(pbClient.authStore.model); } /** * Loads authentication state from Next.js cookies into the PocketBase client. * Call this in server components/routes before checking auth. */ export function loadAuthFromCookies( pbClient: PocketBase, cookieStore: ReadonlyRequestCookies, ): void { const cookie = cookieStore.get("pb_auth"); if (cookie) { pbClient.authStore.loadFromCookie(`pb_auth=${cookie.value}`); } } /** * Maps a PocketBase record to our typed User interface. */ function mapRecordToUser(record: RecordModel): User { return { id: record.id, email: record.email as string, garminConnected: record.garminConnected as boolean, garminOauth1Token: record.garminOauth1Token as string, garminOauth2Token: record.garminOauth2Token as string, garminTokenExpiresAt: new Date(record.garminTokenExpiresAt as string), calendarToken: record.calendarToken as string, lastPeriodDate: new Date(record.lastPeriodDate as string), cycleLength: record.cycleLength as number, notificationTime: record.notificationTime as string, timezone: record.timezone as string, activeOverrides: (record.activeOverrides as OverrideType[]) || [], created: new Date(record.created as string), updated: new Date(record.updated as string), }; }