173 lines
5.1 KiB
TypeScript
173 lines
5.1 KiB
TypeScript
import { type PrismaClient } from "@trigger.dev/database";
|
|
import { prisma } from "~/db.server";
|
|
import { BranchTrackingConfigSchema } from "~/v3/github";
|
|
import { env } from "~/env.server";
|
|
import { findProjectBySlug } from "~/models/project.server";
|
|
import { err, fromPromise, ok, ResultAsync } from "neverthrow";
|
|
import { BuildSettingsSchema } from "~/v3/buildSettings";
|
|
|
|
export class ProjectSettingsPresenter {
|
|
#prismaClient: PrismaClient;
|
|
|
|
constructor(prismaClient: PrismaClient = prisma) {
|
|
this.#prismaClient = prismaClient;
|
|
}
|
|
|
|
getProjectSettings(organizationSlug: string, projectSlug: string, userId: string) {
|
|
const githubAppEnabled = env.GITHUB_APP_ENABLED === "1";
|
|
|
|
const getProject = () =>
|
|
fromPromise(findProjectBySlug(organizationSlug, projectSlug, userId), (error) => ({
|
|
type: "other" as const,
|
|
cause: error,
|
|
}))
|
|
.andThen((project) => {
|
|
if (!project) {
|
|
return err({ type: "project_not_found" as const });
|
|
}
|
|
return ok(project);
|
|
})
|
|
.map((project) => {
|
|
const buildSettingsOrFailure = BuildSettingsSchema.safeParse(project.buildSettings);
|
|
const buildSettings = buildSettingsOrFailure.success
|
|
? buildSettingsOrFailure.data
|
|
: undefined;
|
|
return { ...project, buildSettings };
|
|
});
|
|
|
|
if (!githubAppEnabled) {
|
|
return getProject().map(({ buildSettings }) => ({
|
|
gitHubApp: {
|
|
enabled: false,
|
|
connectedRepository: undefined,
|
|
installations: undefined,
|
|
isPreviewEnvironmentEnabled: undefined,
|
|
},
|
|
buildSettings,
|
|
}));
|
|
}
|
|
|
|
const findConnectedGithubRepository = (projectId: string) =>
|
|
fromPromise(
|
|
this.#prismaClient.connectedGithubRepository.findFirst({
|
|
where: {
|
|
projectId,
|
|
repository: {
|
|
installation: {
|
|
deletedAt: null,
|
|
suspendedAt: null,
|
|
},
|
|
},
|
|
},
|
|
select: {
|
|
branchTracking: true,
|
|
previewDeploymentsEnabled: true,
|
|
createdAt: true,
|
|
repository: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
fullName: true,
|
|
htmlUrl: true,
|
|
private: true,
|
|
},
|
|
},
|
|
},
|
|
}),
|
|
(error) => ({
|
|
type: "other" as const,
|
|
cause: error,
|
|
})
|
|
).map((connectedGithubRepository) => {
|
|
if (!connectedGithubRepository) {
|
|
return undefined;
|
|
}
|
|
|
|
const branchTrackingOrFailure = BranchTrackingConfigSchema.safeParse(
|
|
connectedGithubRepository.branchTracking
|
|
);
|
|
const branchTracking = branchTrackingOrFailure.success
|
|
? branchTrackingOrFailure.data
|
|
: undefined;
|
|
|
|
return {
|
|
...connectedGithubRepository,
|
|
branchTracking,
|
|
};
|
|
});
|
|
|
|
const listGithubAppInstallations = (organizationId: string) =>
|
|
fromPromise(
|
|
this.#prismaClient.githubAppInstallation.findMany({
|
|
where: {
|
|
organizationId,
|
|
deletedAt: null,
|
|
suspendedAt: null,
|
|
},
|
|
select: {
|
|
id: true,
|
|
accountHandle: true,
|
|
targetType: true,
|
|
appInstallationId: true,
|
|
repositories: {
|
|
select: {
|
|
id: true,
|
|
name: true,
|
|
fullName: true,
|
|
htmlUrl: true,
|
|
private: true,
|
|
},
|
|
// Most installations will only have a couple of repos so loading them here should be fine.
|
|
// However, there might be outlier organizations so it's best to expose the installation repos
|
|
// via a resource endpoint and filter on user input.
|
|
take: 200,
|
|
},
|
|
},
|
|
take: 20,
|
|
orderBy: {
|
|
createdAt: "desc",
|
|
},
|
|
}),
|
|
(error) => ({
|
|
type: "other" as const,
|
|
cause: error,
|
|
})
|
|
);
|
|
|
|
const isPreviewEnvironmentEnabled = (projectId: string) =>
|
|
fromPromise(
|
|
this.#prismaClient.runtimeEnvironment.findFirst({
|
|
select: {
|
|
id: true,
|
|
},
|
|
where: {
|
|
projectId: projectId,
|
|
slug: "preview",
|
|
},
|
|
}),
|
|
(error) => ({
|
|
type: "other" as const,
|
|
cause: error,
|
|
})
|
|
).map((previewEnvironment) => previewEnvironment !== null);
|
|
|
|
return getProject().andThen((project) =>
|
|
ResultAsync.combine([
|
|
isPreviewEnvironmentEnabled(project.id),
|
|
findConnectedGithubRepository(project.id),
|
|
listGithubAppInstallations(project.organizationId),
|
|
]).map(
|
|
([isPreviewEnvironmentEnabled, connectedGithubRepository, githubAppInstallations]) => ({
|
|
gitHubApp: {
|
|
enabled: true,
|
|
connectedRepository: connectedGithubRepository,
|
|
installations: githubAppInstallations,
|
|
isPreviewEnvironmentEnabled,
|
|
},
|
|
buildSettings: project.buildSettings,
|
|
})
|
|
)
|
|
);
|
|
}
|
|
}
|