1import type { ElementType } from "react";
2import type { SourceControlProviderInfo } from "@t3tools/contracts";
3import { sourceControlClients } from "@t3tools/client-runtime/source-control-clients";
4import type {
5 ChangeRequestTerminology,
6 SourceControlClientDefinition,
7} from "@t3tools/client-runtime/source-control-clients";
8import {
9 AzureDevOpsIcon,
10 BitbucketIcon,
11 ForgejoIcon,
12 GitCafeIcon,
13 GitHubIcon,
14 GitLabIcon,
15} from "./components/Icons";
16import { PullRequestGlyph } from "~/components/pullRequest/pullRequestIcons";
17
18export type { ChangeRequestTerminology } from "@t3tools/client-runtime/source-control-clients";
19
20type SourceControlIcon = ElementType<{ className?: string }>;
21
22/** Web art for each definition `icon` key; a key without art draws the change request glyph. */
23const SOURCE_CONTROL_ICONS: Partial<Record<string, SourceControlIcon>> = {
24 github: GitHubIcon,
25 gitlab: GitLabIcon,
26 forgejo: ForgejoIcon,
27 bitbucket: BitbucketIcon,
28 "azure-devops": AzureDevOpsIcon,
29 gitcafe: GitCafeIcon,
30};
31
32export function sourceControlIcon(definition: SourceControlClientDefinition): SourceControlIcon {
33 return SOURCE_CONTROL_ICONS[definition.icon] ?? PullRequestGlyph.pullRequest;
34}
35
36export interface SourceControlPresentation {
37 readonly definition: SourceControlClientDefinition;
38 readonly providerName: string;
39 readonly terminology: ChangeRequestTerminology;
40 readonly Icon: SourceControlIcon;
41}
42
43function presentDefinition(
44 definition: SourceControlClientDefinition,
45 providerName: string,
46): SourceControlPresentation {
47 return {
48 definition,
49 providerName,
50 terminology: definition.changeRequest,
51 Icon: sourceControlIcon(definition),
52 };
53}
54
55/** Named as the server reported the host, e.g. "GitHub Self-Hosted", when it reported one. */
56export function getSourceControlPresentation(
57 provider: SourceControlProviderInfo | null | undefined,
58): SourceControlPresentation {
59 const definition = sourceControlClients.get(provider?.kind);
60 return presentDefinition(definition, provider?.name || definition.label);
61}
62
63/** For surfaces that know only the host kind, such as a change request row or filter. */
64export function getSourceControlPresentationForKind(kind: string): SourceControlPresentation {
65 const definition = sourceControlClients.get(kind);
66 return presentDefinition(definition, definition.label);
67}