c7861be520
Once this is merged, oxlint is at a pretty sensible baseline. **Enable `no-unused-vars`, `typescript/consistent-type-imports`, and `import/no-duplicates` lint rules** Turns on three previously-disabled oxlint rules across the monorepo and fixes all violations: - **`no-unused-vars`** – enabled as an error with standard ignore patterns: unused function arguments are ignored by default (`args: "none"`), variables/caught errors/destructured array elements prefixed with `_` are allowed, and rest siblings are permitted. - **`typescript/consistent-type-imports`** – enforced as an error; all type-only imports now use the `import type` syntax. - **`import/no-duplicates`** – enforced as an error; duplicate import statements from the same module have been merged. The remaining commits clean up the violations found across the codebase: removing unused variables/imports/type aliases, adding `_` prefixes to intentionally unused bindings, fixing duplicate imports, and converting value imports to `import type` where appropriate.
87 lines
2.6 KiB
TypeScript
87 lines
2.6 KiB
TypeScript
import { DateFormatter } from "@internationalized/date";
|
|
import type { PrismaClient } from "@trigger.dev/database";
|
|
import { prisma } from "~/db.server";
|
|
import { featuresForRequest } from "~/features.server";
|
|
import { DeleteProjectService } from "./deleteProject.server";
|
|
import { getCurrentPlan } from "./platform.v3.server";
|
|
|
|
export class DeleteOrganizationService {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
public async call({
|
|
organizationSlug,
|
|
userId,
|
|
request,
|
|
}: {
|
|
organizationSlug: string;
|
|
userId: string;
|
|
request: Request;
|
|
}) {
|
|
const organization = await this.#prismaClient.organization.findFirst({
|
|
include: {
|
|
projects: true,
|
|
members: true,
|
|
},
|
|
where: {
|
|
slug: organizationSlug,
|
|
members: { some: { userId: userId } },
|
|
},
|
|
});
|
|
|
|
if (!organization) {
|
|
throw new Error("Organization not found");
|
|
}
|
|
|
|
if (organization.deletedAt) {
|
|
throw new Error("Organization already deleted");
|
|
}
|
|
|
|
//Check if they have an active subscription
|
|
const { isManagedCloud } = featuresForRequest(request);
|
|
const currentPlan = isManagedCloud ? await getCurrentPlan(organization.id) : undefined;
|
|
|
|
if (currentPlan && currentPlan.v3Subscription && currentPlan.v3Subscription.isPaying) {
|
|
//they've cancelled and that date hasn't passed yet
|
|
if (
|
|
currentPlan.v3Subscription.canceledAt &&
|
|
new Date(currentPlan.v3Subscription.canceledAt) > new Date()
|
|
) {
|
|
//a dateformatter that produces results like "Jan 1 2024"
|
|
const dateFormatter = new DateFormatter("en-us", {
|
|
year: "numeric",
|
|
month: "short",
|
|
day: "numeric",
|
|
});
|
|
throw new Error(
|
|
`This Organization has a canceled subscription. You can delete it when the cancelation date (${dateFormatter.format(
|
|
new Date(currentPlan.v3Subscription.canceledAt)
|
|
)}) is in the past.`
|
|
);
|
|
}
|
|
|
|
throw new Error("You can't delete an Organization that has an active subscription");
|
|
}
|
|
|
|
// loop through the projects and delete them
|
|
const projectDeleteService = new DeleteProjectService();
|
|
for (const project of organization.projects) {
|
|
await projectDeleteService.call({ projectId: project.id, userId });
|
|
}
|
|
|
|
//mark the organization as deleted
|
|
await this.#prismaClient.organization.update({
|
|
where: {
|
|
id: organization.id,
|
|
},
|
|
data: {
|
|
runsEnabled: false,
|
|
deletedAt: new Date(),
|
|
},
|
|
});
|
|
}
|
|
}
|