Skip to content
Source
Sign inSign up

pullRequestProjectFilter.ts

52 lines2.0 KB

1import type { EnvironmentId, ProjectId } from "@t3tools/contracts";
2​
3interface FilterProject {
4 readonly id: ProjectId;
5 readonly environmentId: EnvironmentId;
6 readonly repositoryIdentity?: { readonly canonicalKey?: string | undefined } | null | undefined;
7 readonly title: string;
8 readonly workspaceRoot: string;
9}
10​
11function distinguishTitles<Project extends FilterProject>(
12 projects: ReadonlyArray<Project>,
13 suffix: (project: Project) => string,
14) {
15 const counts = new Map<string, number>();
16 for (const project of projects) {
17 counts.set(project.title, (counts.get(project.title) ?? 0) + 1);
18 }
19 return projects.map((project) =>
20 (counts.get(project.title) ?? 0) > 1
21 ? { ...project, title: `${project.title} · ${suffix(project)}` }
22 : project,
23 );
25​
26export function pullRequestFilterProjects<Project extends FilterProject>(
27 projects: ReadonlyArray<Project>,
28 environmentLabels: ReadonlyMap<EnvironmentId, string>,
29 selectedProject?: Pick<FilterProject, "id" | "environmentId">,
30) {
31 const byRepository = new Map<string, Project>();
32 for (const project of projects) {
33 const repository = project.repositoryIdentity?.canonicalKey?.toLowerCase();
34 const key = JSON.stringify([
35 project.environmentId,
36 repository ? ["repository", repository] : ["project", project.id],
37 ]);
38 const selected =
39 project.id === selectedProject?.id && project.environmentId === selectedProject.environmentId;
40 if (!byRepository.has(key) || selected) byRepository.set(key, project);
41 }
42​
43 const byServer = distinguishTitles(
44 [...byRepository.values()],
45 (project) => environmentLabels.get(project.environmentId) ?? project.environmentId,
46 );
47 const byPath = distinguishTitles(byServer, (project) => project.workspaceRoot);
48 const byEnvironment = distinguishTitles(byPath, (project) => project.environmentId);
49 return distinguishTitles(byEnvironment, (project) => project.id).sort((left, right) =>
50 left.title.localeCompare(right.title),
51 );