import "server-only"; import { Prisma } from "@prisma/client"; import { cache as reactCache } from "react"; import { prisma } from "@formbricks/database"; import { logger } from "@formbricks/logger"; import { ZId, ZOptionalNumber, ZString } from "@formbricks/types/common"; import { DatabaseError, ValidationError } from "@formbricks/types/errors"; import type { TProject } from "@formbricks/types/project"; import { ITEMS_PER_PAGE } from "../constants"; import { validateInputs } from "../utils/validate"; const selectProject = { id: true, createdAt: true, updatedAt: true, name: true, organizationId: true, languages: true, recontactDays: true, linkSurveyBranding: true, inAppSurveyBranding: true, config: true, placement: true, clickOutsideClose: true, darkOverlay: true, environments: true, styling: true, logo: true, customHeadScripts: true, }; export const getUserProjects = reactCache( async (userId: string, organizationId: string, page?: number): Promise => { validateInputs([userId, ZString], [organizationId, ZId], [page, ZOptionalNumber]); const orgMembership = await prisma.membership.findFirst({ where: { userId, organizationId, }, }); if (!orgMembership) { throw new ValidationError("User is not a member of this organization"); } let projectWhereClause: Prisma.ProjectWhereInput = {}; if (orgMembership.role === "member") { projectWhereClause = { projectTeams: { some: { team: { teamUsers: { some: { userId, }, }, }, }, }, }; } try { const projects = await prisma.project.findMany({ where: { organizationId, ...projectWhereClause, }, select: selectProject, take: page ? ITEMS_PER_PAGE : undefined, skip: page ? ITEMS_PER_PAGE * (page - 1) : undefined, }); return projects; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } } ); export const getProjects = reactCache(async (organizationId: string, page?: number): Promise => { validateInputs([organizationId, ZId], [page, ZOptionalNumber]); try { const projects = await prisma.project.findMany({ where: { organizationId, }, select: selectProject, take: page ? ITEMS_PER_PAGE : undefined, skip: page ? ITEMS_PER_PAGE * (page - 1) : undefined, }); return projects; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }); export const getProjectByEnvironmentId = reactCache( async (environmentId: string): Promise => { validateInputs([environmentId, ZId]); let projectPrisma; try { projectPrisma = await prisma.project.findFirst({ where: { environments: { some: { id: environmentId, }, }, }, select: selectProject, }); return projectPrisma; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { logger.error(error, "Error getting project by environment id"); throw new DatabaseError(error.message); } throw error; } } ); export const getProject = reactCache(async (projectId: string): Promise => { let projectPrisma; try { projectPrisma = await prisma.project.findUnique({ where: { id: projectId, }, select: selectProject, }); return projectPrisma; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }); export const getOrganizationProjectsCount = reactCache(async (organizationId: string): Promise => { validateInputs([organizationId, ZId]); try { const projects = await prisma.project.count({ where: { organizationId, }, }); return projects; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }); export const getUserProjectEnvironmentsByOrganizationIds = reactCache( async (organizationIds: string[], userId: string): Promise[]> => { validateInputs([organizationIds, ZId.array()], [userId, ZId]); try { if (organizationIds.length === 0) { return []; } const memberships = await prisma.membership.findMany({ where: { userId, organizationId: { in: organizationIds, }, }, }); if (memberships.length === 0) { return []; } const whereConditions: Prisma.ProjectWhereInput[] = memberships.map((membership) => { let projectWhereClause: Prisma.ProjectWhereInput = { organizationId: membership.organizationId, }; if (membership.role === "member") { projectWhereClause = { ...projectWhereClause, projectTeams: { some: { team: { teamUsers: { some: { userId, }, }, }, }, }, }; } return projectWhereClause; }); const projects = await prisma.project.findMany({ where: { OR: whereConditions, }, select: { environments: true }, }); return projects; } catch (err) { if (err instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(err.message); } throw err; } } );