Files
stats/packages/trpc/src/routers/project.ts

159 lines
3.8 KiB
TypeScript

import { z } from 'zod';
import {
db,
getClientById,
getClientByIdCached,
getId,
getProjectByIdCached,
getProjectsByOrganizationId,
} from '@openpanel/db';
import { stripTrailingSlash } from '@openpanel/common';
import { zProject } from '@openpanel/validation';
import { addDays, addHours } from 'date-fns';
import { getProjectAccess } from '../access';
import { TRPCAccessError } from '../errors';
import { createTRPCRouter, protectedProcedure } from '../trpc';
export const projectRouter = createTRPCRouter({
list: protectedProcedure
.input(
z.object({
organizationId: z.string().nullable(),
}),
)
.query(async ({ input: { organizationId } }) => {
if (organizationId === null) return [];
return getProjectsByOrganizationId(organizationId);
}),
update: protectedProcedure
.input(zProject.partial())
.mutation(async ({ input, ctx }) => {
if (!input.id) {
throw new Error('Project ID is required to update a project');
}
const access = await getProjectAccess({
userId: ctx.session.userId,
projectId: input.id,
});
if (!access) {
throw TRPCAccessError('You do not have access to this project');
}
const res = await db.project.update({
where: {
id: input.id,
},
data: {
name: input.name,
crossDomain: input.crossDomain,
filters:
input.filters === undefined ? undefined : input.filters || [],
domain:
input.domain === undefined
? undefined
: input.domain
? stripTrailingSlash(input.domain)
: null,
cors:
input.cors === undefined
? undefined
: input.cors.map((c) => stripTrailingSlash(c)) || [],
},
include: {
clients: {
select: {
id: true,
},
},
},
});
await Promise.all([
getProjectByIdCached.clear(input.id),
res.clients.map((client) => {
getClientByIdCached.clear(client.id);
}),
]);
return res;
}),
create: protectedProcedure
.input(
zProject.omit({ id: true }).merge(
z.object({
organizationId: z.string(),
}),
),
)
.mutation(async ({ input }) => {
return db.project.create({
data: {
id: await getId('project', input.name),
organizationId: input.organizationId,
name: input.name,
domain: input.domain,
cors: input.cors,
crossDomain: input.crossDomain,
filters: [],
},
});
}),
delete: protectedProcedure
.input(
z.object({
projectId: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
const access = await getProjectAccess({
userId: ctx.session.userId,
projectId: input.projectId,
});
if (!access) {
throw TRPCAccessError('You do not have access to this project');
}
await db.project.update({
where: {
id: input.projectId,
},
data: {
deleteAt: addHours(new Date(), 24),
},
});
return true;
}),
cancelDeletion: protectedProcedure
.input(
z.object({
projectId: z.string(),
}),
)
.mutation(async ({ input, ctx }) => {
const access = await getProjectAccess({
userId: ctx.session.userId,
projectId: input.projectId,
});
if (!access) {
throw TRPCAccessError('You do not have access to this project');
}
await db.project.update({
where: {
id: input.projectId,
},
data: {
deleteAt: null,
},
});
return true;
}),
});