import PocketBase from 'pocketbase'; import { redirect } from '@sveltejs/kit'; import type { RequestEvent } from '@sveltejs/kit'; import { SERVER_IP } from '$app/env/public'; import { PB_EMAIL, PB_PASSWORD } from '$app/env/private'; export const PB_ENDPOINT = import.meta.env.PROD ? '/pb' : `http://${SERVER_IP}:8090`; // Server-side PB client, pre-authenticated as the given user's token. // Used for CRUD as the authenticated user so PB collection rules apply // (famId scoping) instead of running everything as superuser. export function createPbClient(token?: string) { const pb = new PocketBase(PB_ENDPOINT); if (token) pb.authStore.save(token, null); return pb; } // Authenticated PB client for the current request's admin/member session. // Requires an active session; redirects to /login otherwise. export function pbUser(event: RequestEvent) { if (!event.locals.user || !event.locals.pbToken) { throw redirect(303, '/login'); } return createPbClient(event.locals.pbToken); } // Superuser PB client (memoized). Reserved for server-only privileged // operations that must bypass collection rules: creating child users, minting // OTP-login tokens, and verifying OTPs against the superuser-only otp. let superClient: PocketBase | null = null; export async function createSuperClient() { if (superClient) return superClient; const pb = new PocketBase(PB_ENDPOINT); await pb.collection('_superusers').authWithPassword(String(PB_EMAIL), String(PB_PASSWORD)); superClient = pb; return pb; } // Superuser CRUD facade, built on the memoized SDK superuser client. All // server PB access (authenticated user + superuser) lives in this one module. export const pbAdmin = { async getList(collection: string, filter = '') { const pb = await createSuperClient(); const options: { filter?: string } = {}; if (filter) options.filter = filter; return pb.collection(collection).getFullList(options); }, async getOne(collection: string, id: string) { const pb = await createSuperClient(); return pb.collection(collection).getOne(id); }, async create(collection: string, data: Record) { const pb = await createSuperClient(); return pb.collection(collection).create(data); }, async update(collection: string, id: string, data: Record) { const pb = await createSuperClient(); return pb.collection(collection).update(id, data); }, async remove(collection: string, id: string) { const pb = await createSuperClient(); return pb.collection(collection).delete(id); } };