Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/frontend/packages/swarm-ui/src/agent/detail/account-api.ts

72 lines
2.3 KiB
TypeScript

// The routes and request body behind linking, listing and deleting an
// external forge account. Pure, so `npm test` runs them without a browser.
/** The kinds that share the label + URL + token shape. */
export type ForgeLinkKind = "forge" | "gitlab";
/** `hive_types::Ident`, which the controller checks for the label. */
export const LABEL_PATTERN = "[a-z0-9\\-]{1,63}";
function agentBase(hive: string, agent: string): string {
return `/api/hives/${encodeURIComponent(hive)}/agents/${encodeURIComponent(agent)}`;
}
/** PUT target for linking `label` under `kind`. */
export function linkUrl(
hive: string,
agent: string,
kind: ForgeLinkKind,
label: string,
): string {
const route = kind === "gitlab" ? "gitlab-accounts" : "forge-accounts";
return `${agentBase(hive, agent)}/${route}/${encodeURIComponent(label)}`;
}
/** The PUT body; the token is sent as typed, the URL trimmed. */
export function linkBody(url: string, token: string): string {
return JSON.stringify({ url: url.trim(), token });
}
/** GET target for the agent's linked accounts. */
export function listUrl(hive: string, agent: string): string {
return `${agentBase(hive, agent)}/linked-accounts`;
}
/** DELETE target for one linked account, as listed by `listUrl`. */
export function deleteUrl(
hive: string,
agent: string,
a: { kind: string; name: string },
): string {
const base = agentBase(hive, agent);
const name = encodeURIComponent(a.name);
switch (a.kind) {
case "matrix":
return `${base}/matrix-accounts/${name}`;
case "forgejo":
return `${base}/forge-accounts/${name}`;
case "gitlab":
return `${base}/gitlab-accounts/${name}`;
case "github":
return `${base}/github-account`;
default:
return `${base}/backend-env`;
}
}
/** A message for input the controller would refuse anyway, or null. The
* controller's own URL rule stays the gate and its 400 is shown as is. */
export function checkLink(
label: string,
url: string,
token: string,
): string | null {
if (!new RegExp(`^${LABEL_PATTERN}$`).test(label)) {
return "label: 1-63 chars, lowercase letters, digits, hyphen";
}
if (!/^https?:\/\/\S+$/.test(url.trim())) {
return "URL must start with http:// or https://";
}
if (token === "") return "token is required";
return null;
}