import { ReqHandler } from "@ethicdevs/react-monolith";
import type { RepositoryWithParentAndForkedFromRepos } from "../../types";
import { Const } from "../../const";
import { AppRoute, AppRoutesParams } from "../../routes";
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
import { makeUsersService } from "../../services/user";
import {
PullRequestFormState,
RepositoryPullRequestCreateFormVariant,
RepositoryPullRequestTarget,
} from "../../islands/RepositoryPullRequestCreateForm";
import RepositoryPullRequestCreateView, {
RepositoryPullRequestCreateViewProps,
} from "../../views/repository/RepositoryPullRequestCreateView";
const getRepositoryPullRequestCreateView: 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 { from_branch } =
request.query as AppRoutesParams[AppRoute.REPOSITORY_PULL_REQUEST_CREATE]["querystring"];
const { orgSlug, repoSlug } =
request.params as AppRoutesParams[AppRoute.REPOSITORY_PULL_REQUEST_CREATE]["params"];
const orgService = makeOrganizationService({ request });
const repoService = makeRepositoryService({ request });
const usersService = makeUsersService({ request });
const parentOrg = await orgService.getOrganizationBySlug(orgSlug);
const repo = await repoService.getRepository(orgSlug, repoSlug);
if (parentOrg == null || repo == null) {
return reply.status(404).callNotFound();
}
const branches = await repoService.getRepositoryBranches(repo);
const currentUserForks = await repoService.getCurrentUserRepositoryForks(
repo
);
const currentUserForksRepos = await currentUserForks.reduce(
async (accP, r) => {
let acc = await accP;
acc = {
...acc,
[`${r.organization.slug}/${r.slug}`]: {
repo: r,
branches: await repoService.getRepositoryBranches(r),
},
};
return acc;
},
Promise.resolve({}) as Promise<{
[repoSlug: string]: {
repo: RepositoryWithParentAndForkedFromRepos;
branches: string[];
};
}>
);
const [personalOrg] = await usersService.getUserOrganizations(
request.session.data.curr_user_uid,
true
);
let variant: RepositoryPullRequestCreateFormVariant;
if (from_branch == null) {
variant = {
state: PullRequestFormState.CONFIGURE,
data: {
sources: {
[parentOrg.slug]: {
org: parentOrg,
repos: {
[`${parentOrg.slug}/${repo.slug}`]: {
repo: { ...repo, organization: parentOrg },
branches,
},
},
},
...(currentUserForks.length >= 1 && {
[personalOrg.slug]: {
org: personalOrg,
repos: currentUserForksRepos,
},
}),
},
target: {
branch: from_branch || Const.PRIMARY_BRANCH_REF,
parentOrg,
repo,
},
},
};
} else {
let source: RepositoryPullRequestTarget = {
branch: from_branch,
parentOrg,
repo,
};
let target: RepositoryPullRequestTarget = {
branch: Const.PRIMARY_BRANCH_REF,
parentOrg,
repo,
};
const orgRepoBranchRegExp = /^([\w\-_\.]+)\/([\w\-_\.]+)@(.*)/i;
const matches = from_branch.match(orgRepoBranchRegExp);
if (matches != null && Array.isArray(matches)) {
const [_, targetOrgSlug, targetRepoSlug, targetFromBranch] = matches;
const targetParentOrg = await orgService.getOrganizationBySlug(
targetOrgSlug
);
const targetRepo = await repoService.getRepository(
targetOrgSlug,
targetRepoSlug
);
if (targetParentOrg == null || targetRepo == null) {
return reply.status(404).callNotFound();
}
const fileDiffs = await repoService.getRepositoryRefDiff(
repo,
Const.PRIMARY_BRANCH_REF,
targetFromBranch
);
target = {
branch: from_branch,
parentOrg: targetParentOrg,
repo: targetRepo,
};
variant = {
state: PullRequestFormState.COMPARE,
data: {
source,
target,
fileDiffs,
},
};
} else {
const fileDiffs = await repoService.getRepositoryRefDiff(
repo,
Const.PRIMARY_BRANCH_REF,
from_branch
);
variant = {
state: PullRequestFormState.COMPARE,
data: {
source: {
branch: Const.PRIMARY_BRANCH_REF,
parentOrg,
repo,
},
target,
fileDiffs,
},
};
}
}
const reqHandler = reply.makeRequestHandler(request, reply);
return reqHandler<RepositoryPullRequestCreateViewProps>(
RepositoryPullRequestCreateView.name,
{
errorMessage: null,
initialValues: {},
parentOrg,
repo,
variant,
}
);
};
export default getRepositoryPullRequestCreateView;