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 });
usersService;
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 repos = await currentUserForks.reduce(
async (accP, r) => {
let acc = await accP;
acc = {
...acc,
[r.slug]: {
repo: r as any,
branches: await repoService.getRepositoryBranches(r),
},
};
return acc;
},
Promise.resolve({}) as Promise<{
[repoSlug: string]: {
repo: RepositoryWithParentAndForkedFromRepos;
branches: string[];
};
}>
);
let variant: RepositoryPullRequestCreateFormVariant;
if (from_branch == null) {
variant = {
state: PullRequestFormState.CONFIGURE,
data: {
sources: {
[parentOrg.slug]: {
org: parentOrg,
repos: {
[repo.slug]: { repo: repo as any, branches },
...repos,
},
},
},
target: {
branch: from_branch || Const.PRIMARY_BRANCH_REF,
parentOrg,
repo,
},
},
};
} else {
let target: RepositoryPullRequestTarget = {
branch: from_branch,
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: {
branch: Const.PRIMARY_BRANCH_REF,
parentOrg,
repo,
},
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;