import { type WorkloadType } from "@trigger.dev/database"; import { type Project } from "~/models/project.server"; import { type User } from "~/models/user.server"; import { FEATURE_FLAG } from "~/v3/featureFlags"; import { makeFlag } from "~/v3/featureFlags.server"; import { defaultVisibilityFilter, resolveComputeAccess } from "~/v3/regionAccess.server"; import { BasePresenter } from "./basePresenter.server"; import { getCurrentPlan } from "~/services/platform.v3.server"; export type Region = { id: string; name: string; masterQueue: string; description?: string; cloudProvider?: string; location?: string; staticIPs?: string | null; isDefault: boolean; isHidden: boolean; workloadType: WorkloadType; }; export class RegionsPresenter extends BasePresenter { public async call({ userId, projectSlug, isAdmin = false, }: { userId: User["id"]; projectSlug: Project["slug"]; isAdmin?: boolean; }) { const project = await this._replica.project.findFirst({ select: { id: true, organizationId: true, defaultWorkerGroupId: true, allowedWorkerQueues: true, organization: { select: { featureFlags: true }, }, }, where: { slug: projectSlug, organization: { members: { some: { userId, }, }, }, }, }); if (!project) { throw new Error("Project not found"); } const getFlag = makeFlag(this._replica); const defaultWorkerInstanceGroupId = await getFlag({ key: FEATURE_FLAG.defaultWorkerInstanceGroupId, }); if (!defaultWorkerInstanceGroupId) { throw new Error("Default worker instance group not found"); } const hasComputeAccess = await resolveComputeAccess( this._replica, project.organization.featureFlags ); const visibleRegions = await this._replica.workerInstanceGroup.findMany({ select: { id: true, name: true, masterQueue: true, description: true, cloudProvider: true, location: true, staticIPs: true, hidden: true, workloadType: true, }, where: isAdmin ? undefined : // Hide hidden unless they're allowed to use them project.allowedWorkerQueues.length > 0 ? { masterQueue: { in: project.allowedWorkerQueues }, } : defaultVisibilityFilter(hasComputeAccess), orderBy: { name: "asc", }, }); const regions: Region[] = visibleRegions.map((region) => ({ id: region.id, name: region.name, masterQueue: region.masterQueue, description: region.description ?? undefined, cloudProvider: region.cloudProvider ?? undefined, location: region.location ?? undefined, staticIPs: region.staticIPs ?? undefined, isDefault: region.id === defaultWorkerInstanceGroupId, isHidden: region.hidden, workloadType: region.workloadType, })); if (project.defaultWorkerGroupId) { const defaultWorkerGroup = await this._replica.workerInstanceGroup.findFirst({ select: { id: true, name: true, masterQueue: true, description: true, cloudProvider: true, location: true, staticIPs: true, hidden: true, workloadType: true, }, where: { id: project.defaultWorkerGroupId }, }); if (defaultWorkerGroup) { // Unset the default region const defaultRegion = regions.find((region) => region.isDefault); if (defaultRegion) { defaultRegion.isDefault = false; } regions.push({ id: defaultWorkerGroup.id, name: defaultWorkerGroup.name, masterQueue: defaultWorkerGroup.masterQueue, description: defaultWorkerGroup.description ?? undefined, cloudProvider: defaultWorkerGroup.cloudProvider ?? undefined, location: defaultWorkerGroup.location ?? undefined, staticIPs: defaultWorkerGroup.staticIPs ?? undefined, isDefault: true, isHidden: defaultWorkerGroup.hidden, workloadType: defaultWorkerGroup.workloadType, }); } } // Default first const sorted = regions.sort((a, b) => { if (a.isDefault) return -1; if (b.isDefault) return 1; return a.name.localeCompare(b.name); }); // Remove later duplicates let unique = sorted.filter((region, index, self) => { const firstIndex = self.findIndex((t) => t.id === region.id); return index === firstIndex; }); // Don't show static IPs for free users // Even if they had the IPs they wouldn't work, but this makes it less confusing const currentPlan = await getCurrentPlan(project.organizationId); const isPaying = currentPlan?.v3Subscription.isPaying === true; if (!isPaying) { unique = unique.map((region) => ({ ...region, staticIPs: region.staticIPs ? null : undefined, })); } return { regions: unique.sort((a, b) => a.name.localeCompare(b.name)), isPaying, }; } }