1const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
2const LOGGED_IN_PATTERN = /Logged in to .+? as\s+([^\s(]+)/iu;
3
4export interface GitLabAuthStatusHost {
5 readonly host: string;
6 readonly account: string | null;
7}
8
9export function parseGitLabAuthStatusHosts(text: string): ReadonlyArray<GitLabAuthStatusHost> {
10 const hosts: GitLabAuthStatusHost[] = [];
11 let currentHost: string | null = null;
12 let currentLines: string[] = [];
13
14 const flush = () => {
15 if (currentHost === null) return;
16
17 const account = LOGGED_IN_PATTERN.exec(currentLines.join("\n"))?.[1]?.trim() || null;
18 hosts.push({ host: currentHost, account });
19 currentHost = null;
20 currentLines = [];
21 };
22
23 for (const rawLine of text.split(/\r?\n/)) {
24 const line = rawLine.trim();
25 if (line.length === 0) continue;
26
27 const isHostLine =
28 rawLine.length === rawLine.trimStart().length && HOST_LINE_PATTERN.test(line);
29 if (isHostLine) {
30 flush();
31 currentHost = line.toLowerCase();
32 continue;
33 }
34
35 if (currentHost !== null) {
36 currentLines.push(line);
37 }
38 }
39
40 flush();
41 return hosts;
42}
43
44export function findAuthenticatedGitLabHost(
45 hosts: ReadonlyArray<GitLabAuthStatusHost>,
46): GitLabAuthStatusHost | undefined {
47 return hosts.find((host) => host.account !== null);
48}