import { and, desc, eq, isNull } from "drizzle-orm"; import { db } from "@/db"; import { projects } from "@/db/schema"; import { AppError } from "@/server/lib/errors"; async function listProjects(organizationId: string) { return db.query.projects.findMany({ where: eq(projects.organizationId, organizationId), orderBy: [desc(projects.createdAt), desc(projects.id)], }); } async function getDefaultProjectForOrganization(organizationId: string) { return db.query.projects.findFirst({ where: and( eq(projects.organizationId, organizationId), eq(projects.name, "Default"), isNull(projects.domain), ), orderBy: [desc(projects.createdAt), desc(projects.id)], }); } async function getProjectForOrganization( projectId: string, organizationId: string, ) { return db.query.projects.findFirst({ where: and( eq(projects.id, projectId), eq(projects.organizationId, organizationId), ), }); } async function getProjectById(projectId: string) { return db.query.projects.findFirst({ where: eq(projects.id, projectId), }); } async function createProject( organizationId: string, name: string, domain?: string, ) { const id = crypto.randomUUID(); await db.insert(projects).values({ id, organizationId, name, domain, }); return id; } async function tryCreateDefaultProject(organizationId: string) { const id = crypto.randomUUID(); const inserted = await db .insert(projects) .values({ id, organizationId, name: "Default", domain: null, }) .onConflictDoNothing() .returning({ id: projects.id }); return inserted.length > 0 ? id : null; } async function deleteProject(projectId: string, organizationId: string) { const project = await getProjectForOrganization(projectId, organizationId); if (!project) { throw new AppError("NOT_FOUND"); } await db .delete(projects) .where( and( eq(projects.id, projectId), eq(projects.organizationId, organizationId), ), ); } export const ProjectRepository = { listProjects, getDefaultProjectForOrganization, getProjectForOrganization, getProjectById, createProject, tryCreateDefaultProject, deleteProject, } as const;