import { ReqHandler } from "@ethicdevs/react-monolith";
import { AppRoute, AppRoutesParams } from "../../routes";
import {
PullRequestFormState,
RepositoryPullRequestCreateFormVariant,
} from "../../islands/RepositoryPullRequestCreateForm";
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
import { makeRepositoryService } from "../../services/repository";
import { makeUsersService } from "../../services/user";
import RepositoryPullRequestCreateView, {
RepositoryPullRequestCreateViewProps,
} from "../../views/repository/RepositoryPullRequestCreateView";
import { RepositoryFileDiff } from "app/types";
const postRepositoryPullRequestCreateAction: ReqHandler = async (
request,
reply
) => {
if (
request.session.data.authenticated === false ||
request.session.data.curr_user_uid == null
) {
reply.redirect(302, request.namedViewsPathMap[AppRoute.AUTH_LOGIN]);
return reply;
}
const { orgSlug, repoSlug } =
request.params as AppRoutesParams[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]["params"];
const {
description,
summary,
state_from: fromState,
state_dest: desiredState,
source_parent_org_slug: sourceParentOrgSlug,
source_repository_from_branch: sourceRepoFromBranch,
source_repository_slug: sourceRepoSlug,
target_parent_org_slug: targetParentOrgSlug,
target_repository_dest_branch: targetRepoDestBranch,
target_repository_slug: targetRepoSlug,
} = request.body as AppRoutesParams[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]["body"];
const orgService = makeOrganizationService({ request });
const repoService = makeRepositoryService({ request });
const pullsService = makePullRequestService({ request });
const usersService = makeUsersService({ request });
const currentUser = await usersService.getUserById(
request.session.data.curr_user_uid
);
if (currentUser == null) {
reply.redirect(302, request.namedViewsPathMap[AppRoute.AUTH_LOGIN]);
return reply;
}
const parentOrg = await orgService.getOrganizationBySlug(orgSlug);
const repo = await repoService.getRepository(orgSlug, repoSlug);
if (parentOrg == null || repo == null) {
return reply.status(404).callNotFound();
}
if (
fromState === PullRequestFormState.ERROR ||
desiredState === PullRequestFormState.CONFIGURE
) {
let redirectUri =
request.namedViewsPathMap[AppRoute.REPOSITORY_PULL_REQUEST_CREATE];
redirectUri = redirectUri
.replace(/:orgSlug/g, parentOrg.slug)
.replace(/:repoSlug/g, repo.slug);
reply.redirect(302, redirectUri);
return reply;
}
let variant: RepositoryPullRequestCreateFormVariant | null = null;
if (desiredState === PullRequestFormState.COMPARE) {
const sourceParentOrg = await orgService.getOrganizationBySlug(
sourceParentOrgSlug
);
const sourceRepo = await repoService.getRepository(
sourceParentOrgSlug,
sourceRepoSlug
);
const targetParentOrg = await orgService.getOrganizationBySlug(
targetParentOrgSlug
);
const targetRepo = await repoService.getRepository(
targetParentOrgSlug,
targetRepoSlug
);
if (
sourceParentOrg == null ||
sourceRepo == null ||
targetParentOrg == null ||
targetRepo == null
) {
return reply.status(404).callNotFound();
}
let fileDiffs = [] as RepositoryFileDiff[];
if (sourceParentOrg.slug === targetParentOrg.slug) {
fileDiffs = await repoService.getRepositoryRefDiff(
sourceRepo,
sourceRepoFromBranch,
targetRepoDestBranch
);
} else {
fileDiffs = await repoService.getRepositoryRemoteRefDiff(
sourceRepo,
sourceRepoFromBranch,
targetRepo,
targetRepoDestBranch
);
}
variant = {
state: desiredState,
data: {
fileDiffs,
source: {
parentOrg: sourceParentOrg,
repo: sourceRepo,
branch: sourceRepoFromBranch,
},
target: {
parentOrg: targetParentOrg,
repo: targetRepo,
branch: targetRepoDestBranch,
},
},
};
} else if (desiredState === PullRequestFormState.DETAILS) {
const sourceRepo = await repoService.getRepository(
sourceParentOrgSlug,
sourceRepoSlug
);
const targetRepo = await repoService.getRepository(
targetParentOrgSlug,
targetRepoSlug
);
if (sourceRepo == null || targetRepo == null) {
return reply.status(404).callNotFound();
}
const pullRequest = await pullsService.createPullRequest({
summary,
textMd: description,
author: currentUser,
source: {
repository: sourceRepo,
fromBranch: sourceRepoFromBranch,
},
target: {
repository: targetRepo,
destBranch: targetRepoDestBranch,
},
});
variant = {
state: desiredState,
data: {
canCurrentUserSubmitPullRequest: false,
pullRequest,
},
};
}
if (variant == null) {
variant = {
state: PullRequestFormState.ERROR,
data: {
errorMessage: "Something went wrong",
},
};
}
const reqHandler = reply.makeRequestHandler(request, reply);
return reqHandler<RepositoryPullRequestCreateViewProps>(
RepositoryPullRequestCreateView.name,
{
errorMessage: null,
initialValues: {},
parentOrg,
repo,
variant,
}
);
};
export default postRepositoryPullRequestCreateAction;