aboutsummaryrefslogtreecommitdiff
path: root/src/queries/prisma
diff options
context:
space:
mode:
Diffstat (limited to 'src/queries/prisma')
-rw-r--r--src/queries/prisma/index.ts8
-rw-r--r--src/queries/prisma/link.ts66
-rw-r--r--src/queries/prisma/pixel.ts60
-rw-r--r--src/queries/prisma/report.ts89
-rw-r--r--src/queries/prisma/segment.ts61
-rw-r--r--src/queries/prisma/team.ts165
-rw-r--r--src/queries/prisma/teamUser.ts66
-rw-r--r--src/queries/prisma/user.ts206
-rw-r--r--src/queries/prisma/website.ts234
9 files changed, 955 insertions, 0 deletions
diff --git a/src/queries/prisma/index.ts b/src/queries/prisma/index.ts
new file mode 100644
index 0000000..b9730f5
--- /dev/null
+++ b/src/queries/prisma/index.ts
@@ -0,0 +1,8 @@
+export * from './link';
+export * from './pixel';
+export * from './report';
+export * from './segment';
+export * from './team';
+export * from './teamUser';
+export * from './user';
+export * from './website';
diff --git a/src/queries/prisma/link.ts b/src/queries/prisma/link.ts
new file mode 100644
index 0000000..9b971de
--- /dev/null
+++ b/src/queries/prisma/link.ts
@@ -0,0 +1,66 @@
+import type { Prisma } from '@/generated/prisma/client';
+import prisma from '@/lib/prisma';
+import type { QueryFilters } from '@/lib/types';
+
+export async function findLink(criteria: Prisma.LinkFindUniqueArgs) {
+ return prisma.client.link.findUnique(criteria);
+}
+
+export async function getLink(linkId: string) {
+ return findLink({
+ where: {
+ id: linkId,
+ },
+ });
+}
+
+export async function getLinks(criteria: Prisma.LinkFindManyArgs, filters: QueryFilters = {}) {
+ const { search } = filters;
+ const { getSearchParameters, pagedQuery } = prisma;
+
+ const where: Prisma.LinkWhereInput = {
+ ...criteria.where,
+ ...getSearchParameters(search, [
+ { name: 'contains' },
+ { url: 'contains' },
+ { slug: 'contains' },
+ ]),
+ };
+
+ return pagedQuery('link', { ...criteria, where }, filters);
+}
+
+export async function getUserLinks(userId: string, filters?: QueryFilters) {
+ return getLinks(
+ {
+ where: {
+ userId,
+ deletedAt: null,
+ },
+ },
+ filters,
+ );
+}
+
+export async function getTeamLinks(teamId: string, filters?: QueryFilters) {
+ return getLinks(
+ {
+ where: {
+ teamId,
+ },
+ },
+ filters,
+ );
+}
+
+export async function createLink(data: Prisma.LinkUncheckedCreateInput) {
+ return prisma.client.link.create({ data });
+}
+
+export async function updateLink(linkId: string, data: any) {
+ return prisma.client.link.update({ where: { id: linkId }, data });
+}
+
+export async function deleteLink(linkId: string) {
+ return prisma.client.link.delete({ where: { id: linkId } });
+}
diff --git a/src/queries/prisma/pixel.ts b/src/queries/prisma/pixel.ts
new file mode 100644
index 0000000..4c9e132
--- /dev/null
+++ b/src/queries/prisma/pixel.ts
@@ -0,0 +1,60 @@
+import type { Prisma } from '@/generated/prisma/client';
+import prisma from '@/lib/prisma';
+import type { QueryFilters } from '@/lib/types';
+
+export async function findPixel(criteria: Prisma.PixelFindUniqueArgs) {
+ return prisma.client.pixel.findUnique(criteria);
+}
+
+export async function getPixel(pixelId: string) {
+ return findPixel({
+ where: {
+ id: pixelId,
+ },
+ });
+}
+
+export async function getPixels(criteria: Prisma.PixelFindManyArgs, filters: QueryFilters = {}) {
+ const { search } = filters;
+
+ const where: Prisma.PixelWhereInput = {
+ ...criteria.where,
+ ...prisma.getSearchParameters(search, [{ name: 'contains' }, { slug: 'contains' }]),
+ };
+
+ return prisma.pagedQuery('pixel', { ...criteria, where }, filters);
+}
+
+export async function getUserPixels(userId: string, filters?: QueryFilters) {
+ return getPixels(
+ {
+ where: {
+ userId,
+ },
+ },
+ filters,
+ );
+}
+
+export async function getTeamPixels(teamId: string, filters?: QueryFilters) {
+ return getPixels(
+ {
+ where: {
+ teamId,
+ },
+ },
+ filters,
+ );
+}
+
+export async function createPixel(data: Prisma.PixelUncheckedCreateInput) {
+ return prisma.client.pixel.create({ data });
+}
+
+export async function updatePixel(pixelId: string, data: any) {
+ return prisma.client.pixel.update({ where: { id: pixelId }, data });
+}
+
+export async function deletePixel(pixelId: string) {
+ return prisma.client.pixel.delete({ where: { id: pixelId } });
+}
diff --git a/src/queries/prisma/report.ts b/src/queries/prisma/report.ts
new file mode 100644
index 0000000..4a5b755
--- /dev/null
+++ b/src/queries/prisma/report.ts
@@ -0,0 +1,89 @@
+import { Prisma } from '@/generated/prisma/client';
+import prisma from '@/lib/prisma';
+import type { QueryFilters } from '@/lib/types';
+
+import ReportFindManyArgs = Prisma.ReportFindManyArgs;
+
+async function findReport(criteria: Prisma.ReportFindUniqueArgs) {
+ return prisma.client.report.findUnique(criteria);
+}
+
+export async function getReport(reportId: string) {
+ return findReport({
+ where: {
+ id: reportId,
+ },
+ });
+}
+
+export async function getReports(criteria: ReportFindManyArgs, filters: QueryFilters = {}) {
+ const { search } = filters;
+
+ const where: Prisma.ReportWhereInput = {
+ ...criteria.where,
+ ...prisma.getSearchParameters(search, [
+ { name: 'contains' },
+ { description: 'contains' },
+ { type: 'contains' },
+ {
+ user: {
+ username: 'contains',
+ },
+ },
+ {
+ website: {
+ name: 'contains',
+ },
+ },
+ {
+ website: {
+ domain: 'contains',
+ },
+ },
+ ]),
+ };
+
+ return prisma.pagedQuery('report', { ...criteria, where }, filters);
+}
+
+export async function getUserReports(userId: string, filters?: QueryFilters) {
+ return getReports(
+ {
+ where: {
+ userId,
+ },
+ include: {
+ website: {
+ select: {
+ domain: true,
+ userId: true,
+ },
+ },
+ },
+ },
+ filters,
+ );
+}
+
+export async function getWebsiteReports(websiteId: string, filters: QueryFilters = {}) {
+ return getReports(
+ {
+ where: {
+ websiteId,
+ },
+ },
+ filters,
+ );
+}
+
+export async function createReport(data: Prisma.ReportUncheckedCreateInput) {
+ return prisma.client.report.create({ data });
+}
+
+export async function updateReport(reportId: string, data: any) {
+ return prisma.client.report.update({ where: { id: reportId }, data });
+}
+
+export async function deleteReport(reportId: string) {
+ return prisma.client.report.delete({ where: { id: reportId } });
+}
diff --git a/src/queries/prisma/segment.ts b/src/queries/prisma/segment.ts
new file mode 100644
index 0000000..3a17d27
--- /dev/null
+++ b/src/queries/prisma/segment.ts
@@ -0,0 +1,61 @@
+import type { Prisma } from '@/generated/prisma/client';
+import prisma from '@/lib/prisma';
+import type { QueryFilters } from '@/lib/types';
+
+async function findSegment(criteria: Prisma.SegmentFindUniqueArgs) {
+ return prisma.client.segment.findUnique(criteria);
+}
+
+export async function getSegment(segmentId: string) {
+ return findSegment({
+ where: {
+ id: segmentId,
+ },
+ });
+}
+
+export async function getSegments(criteria: Prisma.SegmentFindManyArgs, filters: QueryFilters) {
+ const { search } = filters;
+ const { getSearchParameters, pagedQuery } = prisma;
+
+ const where: Prisma.SegmentWhereInput = {
+ ...criteria.where,
+ ...getSearchParameters(search, [
+ {
+ name: 'contains',
+ },
+ ]),
+ };
+
+ return pagedQuery('segment', { ...criteria, where }, filters);
+}
+
+export async function getWebsiteSegment(websiteId: string, segmentId: string) {
+ return prisma.client.segment.findFirst({
+ where: { id: segmentId, websiteId },
+ });
+}
+
+export async function getWebsiteSegments(websiteId: string, type: string, filters?: QueryFilters) {
+ return getSegments(
+ {
+ where: {
+ websiteId,
+ type,
+ },
+ },
+ filters,
+ );
+}
+
+export async function createSegment(data: Prisma.SegmentUncheckedCreateInput) {
+ return prisma.client.segment.create({ data });
+}
+
+export async function updateSegment(SegmentId: string, data: Prisma.SegmentUpdateInput) {
+ return prisma.client.segment.update({ where: { id: SegmentId }, data });
+}
+
+export async function deleteSegment(SegmentId: string) {
+ return prisma.client.segment.delete({ where: { id: SegmentId } });
+}
diff --git a/src/queries/prisma/team.ts b/src/queries/prisma/team.ts
new file mode 100644
index 0000000..5987c1d
--- /dev/null
+++ b/src/queries/prisma/team.ts
@@ -0,0 +1,165 @@
+import { Prisma, type Team } from '@/generated/prisma/client';
+import { ROLES } from '@/lib/constants';
+import { uuid } from '@/lib/crypto';
+import prisma from '@/lib/prisma';
+import type { PageResult, QueryFilters } from '@/lib/types';
+
+import TeamFindManyArgs = Prisma.TeamFindManyArgs;
+
+export async function findTeam(criteria: Prisma.TeamFindUniqueArgs): Promise<Team> {
+ return prisma.client.team.findUnique(criteria);
+}
+
+export async function getTeam(
+ teamId: string,
+ options: { includeMembers?: boolean } = {},
+): Promise<Team> {
+ const { includeMembers } = options;
+
+ return findTeam({
+ where: {
+ id: teamId,
+ },
+ ...(includeMembers && { include: { members: true } }),
+ });
+}
+
+export async function getTeams(
+ criteria: TeamFindManyArgs,
+ filters: QueryFilters,
+): Promise<PageResult<Team[]>> {
+ const { getSearchParameters } = prisma;
+ const { search } = filters;
+
+ const where: Prisma.TeamWhereInput = {
+ ...criteria.where,
+ ...getSearchParameters(search, [{ name: 'contains' }]),
+ };
+
+ return prisma.pagedQuery<TeamFindManyArgs>(
+ 'team',
+ {
+ ...criteria,
+ where,
+ },
+ filters,
+ );
+}
+
+export async function getUserTeams(userId: string, filters: QueryFilters = {}) {
+ return getTeams(
+ {
+ where: {
+ deletedAt: null,
+ members: {
+ some: { userId },
+ },
+ },
+ include: {
+ members: {
+ include: {
+ user: {
+ select: {
+ id: true,
+ username: true,
+ },
+ },
+ },
+ },
+ _count: {
+ select: {
+ websites: {
+ where: { deletedAt: null },
+ },
+ members: {
+ where: {
+ user: { deletedAt: null },
+ },
+ },
+ },
+ },
+ },
+ },
+ filters,
+ );
+}
+
+export async function getAllUserTeams(userId: string) {
+ return prisma.client.team.findMany({
+ where: {
+ deletedAt: null,
+ members: {
+ some: { userId },
+ },
+ },
+ select: {
+ id: true,
+ name: true,
+ logoUrl: true,
+ },
+ });
+}
+
+export async function createTeam(data: Prisma.TeamCreateInput, userId: string): Promise<any> {
+ const { id } = data;
+ const { client, transaction } = prisma;
+
+ return transaction([
+ client.team.create({
+ data,
+ }),
+ client.teamUser.create({
+ data: {
+ id: uuid(),
+ teamId: id,
+ userId,
+ role: ROLES.teamOwner,
+ },
+ }),
+ ]);
+}
+
+export async function updateTeam(teamId: string, data: Prisma.TeamUpdateInput): Promise<Team> {
+ const { client } = prisma;
+
+ return client.team.update({
+ where: {
+ id: teamId,
+ },
+ data: {
+ ...data,
+ updatedAt: new Date(),
+ },
+ });
+}
+
+export async function deleteTeam(teamId: string) {
+ const { client, transaction } = prisma;
+ const cloudMode = !!process.env.CLOUD_MODE;
+
+ if (cloudMode) {
+ return transaction([
+ client.team.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: {
+ id: teamId,
+ },
+ }),
+ ]);
+ }
+
+ return transaction([
+ client.teamUser.deleteMany({
+ where: {
+ teamId,
+ },
+ }),
+ client.team.delete({
+ where: {
+ id: teamId,
+ },
+ }),
+ ]);
+}
diff --git a/src/queries/prisma/teamUser.ts b/src/queries/prisma/teamUser.ts
new file mode 100644
index 0000000..2210dee
--- /dev/null
+++ b/src/queries/prisma/teamUser.ts
@@ -0,0 +1,66 @@
+import { Prisma } from '@/generated/prisma/client';
+import { uuid } from '@/lib/crypto';
+import prisma from '@/lib/prisma';
+import type { QueryFilters } from '@/lib/types';
+
+import TeamUserFindManyArgs = Prisma.TeamUserFindManyArgs;
+
+export async function findTeamUser(criteria: Prisma.TeamUserFindUniqueArgs) {
+ return prisma.client.teamUser.findUnique(criteria);
+}
+
+export async function getTeamUser(teamId: string, userId: string) {
+ return prisma.client.teamUser.findFirst({
+ where: {
+ teamId,
+ userId,
+ },
+ });
+}
+
+export async function getTeamUsers(criteria: TeamUserFindManyArgs, filters?: QueryFilters) {
+ const { search } = filters;
+
+ const where: Prisma.TeamUserWhereInput = {
+ ...criteria.where,
+ ...prisma.getSearchParameters(search, [{ user: { username: 'contains' } }]),
+ };
+
+ return prisma.pagedQuery(
+ 'teamUser',
+ {
+ ...criteria,
+ where,
+ },
+ filters,
+ );
+}
+
+export async function createTeamUser(userId: string, teamId: string, role: string) {
+ return prisma.client.teamUser.create({
+ data: {
+ id: uuid(),
+ userId,
+ teamId,
+ role,
+ },
+ });
+}
+
+export async function updateTeamUser(teamUserId: string, data: Prisma.TeamUserUpdateInput) {
+ return prisma.client.teamUser.update({
+ where: {
+ id: teamUserId,
+ },
+ data,
+ });
+}
+
+export async function deleteTeamUser(teamId: string, userId: string) {
+ return prisma.client.teamUser.deleteMany({
+ where: {
+ teamId,
+ userId,
+ },
+ });
+}
diff --git a/src/queries/prisma/user.ts b/src/queries/prisma/user.ts
new file mode 100644
index 0000000..14376fc
--- /dev/null
+++ b/src/queries/prisma/user.ts
@@ -0,0 +1,206 @@
+import { Prisma } from '@/generated/prisma/client';
+import { ROLES } from '@/lib/constants';
+import { getRandomChars } from '@/lib/generate';
+import prisma from '@/lib/prisma';
+import type { QueryFilters, Role } from '@/lib/types';
+
+import UserFindManyArgs = Prisma.UserFindManyArgs;
+
+export interface GetUserOptions {
+ includePassword?: boolean;
+ showDeleted?: boolean;
+}
+
+async function findUser(criteria: Prisma.UserFindUniqueArgs, options: GetUserOptions = {}) {
+ const { includePassword = false, showDeleted = false } = options;
+
+ return prisma.client.user.findUnique({
+ ...criteria,
+ where: {
+ ...criteria.where,
+ ...(showDeleted && { deletedAt: null }),
+ },
+ select: {
+ id: true,
+ username: true,
+ password: includePassword,
+ role: true,
+ createdAt: true,
+ },
+ });
+}
+
+export async function getUser(userId: string, options: GetUserOptions = {}) {
+ return findUser(
+ {
+ where: {
+ id: userId,
+ },
+ },
+ options,
+ );
+}
+
+export async function getUserByUsername(username: string, options: GetUserOptions = {}) {
+ return findUser({ where: { username } }, options);
+}
+
+export async function getUsers(criteria: UserFindManyArgs, filters: QueryFilters = {}) {
+ const { search } = filters;
+
+ const where: Prisma.UserWhereInput = {
+ ...criteria.where,
+ ...prisma.getSearchParameters(search, [{ username: 'contains' }]),
+ deletedAt: null,
+ };
+
+ return prisma.pagedQuery(
+ 'user',
+ {
+ ...criteria,
+ where,
+ },
+ {
+ orderBy: 'createdAt',
+ sortDescending: true,
+ ...filters,
+ },
+ );
+}
+
+export async function createUser(data: {
+ id: string;
+ username: string;
+ password: string;
+ role: Role;
+}) {
+ return prisma.client.user.create({
+ data,
+ select: {
+ id: true,
+ username: true,
+ role: true,
+ },
+ });
+}
+
+export async function updateUser(userId: string, data: Prisma.UserUpdateInput) {
+ return prisma.client.user.update({
+ where: {
+ id: userId,
+ },
+ data,
+ select: {
+ id: true,
+ username: true,
+ role: true,
+ createdAt: true,
+ },
+ });
+}
+
+export async function deleteUser(userId: string) {
+ const { client, transaction } = prisma;
+ const cloudMode = !!process.env.CLOUD_MODE;
+
+ const websites = await client.website.findMany({
+ where: { userId },
+ });
+
+ let websiteIds = [];
+
+ if (websites.length > 0) {
+ websiteIds = websites.map(a => a.id);
+ }
+
+ const teams = await client.team.findMany({
+ where: {
+ members: {
+ some: {
+ userId,
+ role: ROLES.teamOwner,
+ },
+ },
+ },
+ });
+
+ const teamIds = teams.map(a => a.id);
+
+ if (cloudMode) {
+ return transaction([
+ client.website.updateMany({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: { id: { in: websiteIds } },
+ }),
+ client.user.update({
+ data: {
+ username: getRandomChars(32),
+ deletedAt: new Date(),
+ },
+ where: {
+ id: userId,
+ },
+ }),
+ ]);
+ }
+
+ return transaction([
+ client.eventData.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.sessionData.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.websiteEvent.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.session.deleteMany({
+ where: { websiteId: { in: websiteIds } },
+ }),
+ client.teamUser.deleteMany({
+ where: {
+ OR: [
+ {
+ teamId: {
+ in: teamIds,
+ },
+ },
+ {
+ userId,
+ },
+ ],
+ },
+ }),
+ client.team.deleteMany({
+ where: {
+ id: {
+ in: teamIds,
+ },
+ },
+ }),
+ client.report.deleteMany({
+ where: {
+ OR: [
+ {
+ websiteId: {
+ in: websiteIds,
+ },
+ },
+ {
+ userId,
+ },
+ ],
+ },
+ }),
+ client.website.deleteMany({
+ where: { id: { in: websiteIds } },
+ }),
+ client.user.delete({
+ where: {
+ id: userId,
+ },
+ }),
+ ]);
+}
diff --git a/src/queries/prisma/website.ts b/src/queries/prisma/website.ts
new file mode 100644
index 0000000..79cb724
--- /dev/null
+++ b/src/queries/prisma/website.ts
@@ -0,0 +1,234 @@
+import type { Prisma } from '@/generated/prisma/client';
+import { ROLES } from '@/lib/constants';
+import prisma from '@/lib/prisma';
+import redis from '@/lib/redis';
+import type { QueryFilters } from '@/lib/types';
+
+export async function findWebsite(criteria: Prisma.WebsiteFindUniqueArgs) {
+ return prisma.client.website.findUnique(criteria);
+}
+
+export async function getWebsite(websiteId: string) {
+ return findWebsite({
+ where: {
+ id: websiteId,
+ },
+ });
+}
+
+export async function getSharedWebsite(shareId: string) {
+ return findWebsite({
+ where: {
+ shareId,
+ deletedAt: null,
+ },
+ });
+}
+
+export async function getWebsites(criteria: Prisma.WebsiteFindManyArgs, filters: QueryFilters) {
+ const { search } = filters;
+ const { getSearchParameters, pagedQuery } = prisma;
+
+ const where: Prisma.WebsiteWhereInput = {
+ ...criteria.where,
+ ...getSearchParameters(search, [
+ {
+ name: 'contains',
+ },
+ { domain: 'contains' },
+ ]),
+ deletedAt: null,
+ };
+
+ return pagedQuery('website', { ...criteria, where }, filters);
+}
+
+export async function getAllUserWebsitesIncludingTeamOwner(userId: string, filters?: QueryFilters) {
+ return getWebsites(
+ {
+ where: {
+ OR: [
+ { userId },
+ {
+ team: {
+ deletedAt: null,
+ members: {
+ some: {
+ role: ROLES.teamOwner,
+ userId,
+ },
+ },
+ },
+ },
+ ],
+ },
+ },
+ {
+ orderBy: 'name',
+ ...filters,
+ },
+ );
+}
+
+export async function getUserWebsites(userId: string, filters?: QueryFilters) {
+ return getWebsites(
+ {
+ where: {
+ userId,
+ },
+ include: {
+ user: {
+ select: {
+ username: true,
+ id: true,
+ },
+ },
+ },
+ },
+ {
+ orderBy: 'name',
+ ...filters,
+ },
+ );
+}
+
+export async function getTeamWebsites(teamId: string, filters?: QueryFilters) {
+ return getWebsites(
+ {
+ where: {
+ teamId,
+ },
+ include: {
+ createUser: {
+ select: {
+ id: true,
+ username: true,
+ },
+ },
+ },
+ },
+ filters,
+ );
+}
+
+export async function createWebsite(
+ data: Prisma.WebsiteCreateInput | Prisma.WebsiteUncheckedCreateInput,
+) {
+ return prisma.client.website.create({
+ data,
+ });
+}
+
+export async function updateWebsite(
+ websiteId: string,
+ data: Prisma.WebsiteUpdateInput | Prisma.WebsiteUncheckedUpdateInput,
+) {
+ return prisma.client.website.update({
+ where: {
+ id: websiteId,
+ },
+ data,
+ });
+}
+
+export async function resetWebsite(websiteId: string) {
+ const { client, transaction } = prisma;
+ const cloudMode = !!process.env.CLOUD_MODE;
+
+ return transaction(
+ [
+ client.revenue.deleteMany({
+ where: { websiteId },
+ }),
+ client.eventData.deleteMany({
+ where: { websiteId },
+ }),
+ client.sessionData.deleteMany({
+ where: { websiteId },
+ }),
+ client.websiteEvent.deleteMany({
+ where: { websiteId },
+ }),
+ client.session.deleteMany({
+ where: { websiteId },
+ }),
+ client.website.update({
+ where: { id: websiteId },
+ data: {
+ resetAt: new Date(),
+ },
+ }),
+ ],
+ {
+ timeout: 30000,
+ },
+ ).then(async data => {
+ if (cloudMode) {
+ await redis.client.set(
+ `website:${websiteId}`,
+ data.find(website => website.id),
+ );
+ }
+
+ return data;
+ });
+}
+
+export async function deleteWebsite(websiteId: string) {
+ const { client, transaction } = prisma;
+ const cloudMode = !!process.env.CLOUD_MODE;
+
+ return transaction(
+ [
+ client.revenue.deleteMany({
+ where: { websiteId },
+ }),
+ client.eventData.deleteMany({
+ where: { websiteId },
+ }),
+ client.sessionData.deleteMany({
+ where: { websiteId },
+ }),
+ client.websiteEvent.deleteMany({
+ where: { websiteId },
+ }),
+ client.session.deleteMany({
+ where: { websiteId },
+ }),
+ client.report.deleteMany({
+ where: { websiteId },
+ }),
+ client.segment.deleteMany({
+ where: { websiteId },
+ }),
+ cloudMode
+ ? client.website.update({
+ data: {
+ deletedAt: new Date(),
+ },
+ where: { id: websiteId },
+ })
+ : client.website.delete({
+ where: { id: websiteId },
+ }),
+ ],
+ {
+ timeout: 30000,
+ },
+ ).then(async data => {
+ if (cloudMode) {
+ await redis.client.del(`website:${websiteId}`);
+ }
+
+ return data;
+ });
+}
+
+export async function getWebsiteCount(userId: string) {
+ return prisma.client.website.count({
+ where: {
+ userId,
+ deletedAt: null,
+ },
+ });
+}