9ae0ca64af
* If you have an org with no projects, it displays in the project dropdown with a “New project” button * When creating a new org disable the button whilst it’s doing the request * If an org already had any deleted projects it couldn’t be deleted… * When selecting the best project, factor in deleted ones * Don’t show the cancel button when creating a new org if there are no non-deleted projects * If a project has already been deleted just return
142 lines
3.4 KiB
TypeScript
142 lines
3.4 KiB
TypeScript
import { PrismaClient } from "@trigger.dev/database";
|
|
import { prisma } from "~/db.server";
|
|
import { DeleteEndpointService } from "./endpoints/deleteEndpointService";
|
|
import { logger } from "./logger.server";
|
|
import { DisableScheduleSourceService } from "./schedules/disableScheduleSource.server";
|
|
|
|
type Options = ({ projectId: string } | { projectSlug: string }) & {
|
|
userId: string;
|
|
};
|
|
|
|
export class DeleteProjectService {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call(options: Options) {
|
|
const projectId = await this.#getProjectId(options);
|
|
const project = await this.#prismaClient.project.findFirst({
|
|
include: {
|
|
environments: {
|
|
include: {
|
|
endpoints: true,
|
|
},
|
|
},
|
|
jobs: {
|
|
where: { deletedAt: null },
|
|
include: {
|
|
aliases: {
|
|
where: {
|
|
name: "latest",
|
|
},
|
|
include: {
|
|
version: true,
|
|
},
|
|
take: 1,
|
|
},
|
|
},
|
|
},
|
|
organization: true,
|
|
},
|
|
where: {
|
|
id: projectId,
|
|
organization: { members: { some: { userId: options.userId } } },
|
|
},
|
|
});
|
|
|
|
if (!project) {
|
|
throw new Error("Project not found");
|
|
}
|
|
|
|
if (project.deletedAt) {
|
|
return;
|
|
}
|
|
|
|
//disable and delete all jobs
|
|
const service = new DisableScheduleSourceService();
|
|
for (const environment of project.environments) {
|
|
//disable the event dispatchers
|
|
await this.#prismaClient.eventDispatcher.updateMany({
|
|
where: {
|
|
environmentId: environment.id,
|
|
},
|
|
data: {
|
|
enabled: false,
|
|
},
|
|
});
|
|
const eventDispatchers = await this.#prismaClient.eventDispatcher.findMany({
|
|
where: {
|
|
environmentId: environment.id,
|
|
},
|
|
});
|
|
|
|
logger.info("Deleting jobs", { jobs: project.jobs });
|
|
for (const job of project.jobs) {
|
|
//disable all the job versions
|
|
await this.#prismaClient.jobVersion.updateMany({
|
|
where: {
|
|
jobId: job.id,
|
|
},
|
|
data: {
|
|
status: "DISABLED",
|
|
},
|
|
});
|
|
|
|
await this.#prismaClient.job.update({
|
|
where: {
|
|
id: job.id,
|
|
},
|
|
data: {
|
|
deletedAt: new Date(),
|
|
},
|
|
});
|
|
|
|
//disable scheduled sources
|
|
for (const eventDispatcher of eventDispatchers) {
|
|
await service.call({
|
|
key: job.id,
|
|
dispatcher: eventDispatcher,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
//delete all endpoints
|
|
const deleteEndpointService = new DeleteEndpointService();
|
|
for (const environment of project.environments) {
|
|
for (const endpoint of environment.endpoints) {
|
|
await deleteEndpointService.call(endpoint.id, options.userId);
|
|
}
|
|
}
|
|
|
|
//mark the project as deleted
|
|
await this.#prismaClient.project.update({
|
|
where: {
|
|
id: project.id,
|
|
},
|
|
data: {
|
|
deletedAt: new Date(),
|
|
},
|
|
});
|
|
}
|
|
|
|
async #getProjectId(options: Options) {
|
|
if ("projectId" in options) {
|
|
return options.projectId;
|
|
}
|
|
|
|
const { id } = await this.#prismaClient.project.findFirstOrThrow({
|
|
select: {
|
|
id: true,
|
|
},
|
|
where: {
|
|
slug: options.projectSlug,
|
|
},
|
|
});
|
|
|
|
return id;
|
|
}
|
|
}
|