import { Prisma, PrismaClient } from '@prisma/client'; /** True when database-backed tests can run (see vitest.global-setup.ts). */ export const hasTestDb = Boolean(process.env.TEST_DATABASE_URL); /** Prisma client bound to the test database. Callers own the lifecycle. */ export function createTestPrisma(): PrismaClient { if (!process.env.TEST_DATABASE_URL) { throw new Error('TEST_DATABASE_URL is not set — guard the suite with hasTestDb'); } return new PrismaClient({ datasourceUrl: process.env.TEST_DATABASE_URL }); } /** Unique suffix so suites never collide on unique columns. */ export function uniqueSuffix(): string { return Math.random().toString(36).slice(2, 10); } /** * The owner's Pond Admin grant for a pond created directly through Prisma. * Production paths create it with the pond (PondsService, issue #52); * fixtures that bypass the service need it too, or the owner cannot see * their own pond under the grant-based resolution. */ export async function grantOwnerAdmin( prisma: PrismaClient, pondId: string, ownerId: string, ): Promise { await prisma.roleGrant.create({ data: { pondId, subjectType: 'USER', subjectId: ownerId, role: 'POND_ADMIN', scopeType: 'POND', scopeId: null, effect: 'ALLOW', createdBy: ownerId, }, }); } /** * Deletes the ponds matching `where`, their pages first. * * `Page.pond` deliberately carries no `onDelete: Cascade` — a real purge * (TrashService) removes a pond's contents explicitly and audits it, and a * silent database cascade would hide that. Since issue #302 every pond * created through the api starts with a page, so teardowns that went * straight for `pond.deleteMany` now hit the foreign key. * * Page-owned rows (updates, comments, links, …) do cascade from the page. */ export async function deletePondsWhere( prisma: PrismaClient, where: Prisma.PondWhereInput, ): Promise { const pondIds = (await prisma.pond.findMany({ where, select: { id: true } })).map( (pond) => pond.id, ); if (pondIds.length === 0) return; await prisma.attachment.deleteMany({ where: { pondId: { in: pondIds } } }); await prisma.page.deleteMany({ where: { pondId: { in: pondIds } } }); await prisma.pond.deleteMany({ where: { id: { in: pondIds } } }); }