feat(onboarding): enhance integration setup with Docker discovery and URL templating (#5607)
This commit is contained in:
1 parent
0a6467979a
commit
dd7a4908a3
68 files changed
+2922
-434
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import { objectKeys } from "@homarr/common";
|
||||
|
||||
import { integrationDefs } from "./integration";
|
||||
import type { IntegrationKind } from "./integration";
|
||||
|
||||
export const extractContainerImageName = (image: string): string => image.split("/").at(-1)?.split(":").at(0) ?? "";
|
||||
|
||||
const extractIconSlug = (iconUrl: string): string => {
|
||||
const filename = iconUrl.split("/").pop() ?? "";
|
||||
return filename.replace(/\.(svg|png)$/, "").toLowerCase();
|
||||
};
|
||||
|
||||
export const integrationIconSlugs: Record<IntegrationKind, string> = Object.fromEntries(
|
||||
objectKeys(integrationDefs).map((kind) => [kind, extractIconSlug(integrationDefs[kind].iconUrl)]),
|
||||
) as Record<IntegrationKind, string>;
|
||||
|
||||
const integrationAliases: Partial<Record<IntegrationKind, readonly string[]>> = {
|
||||
piHole: ["pihole", "pi-hole"],
|
||||
adGuardHome: ["adguardhome", "adguard-home", "adguard"],
|
||||
homeAssistant: ["homeassistant", "home-assistant", "hass"],
|
||||
openmediavault: ["omv"],
|
||||
qBittorrent: ["qbittorrent"],
|
||||
sabNzbd: ["sabnzbd"],
|
||||
nzbGet: ["nzbget"],
|
||||
unifiController: ["unifi", "unifi-controller"],
|
||||
jellyseerr: ["jellyseerr"],
|
||||
overseerr: ["overseerr"],
|
||||
dashDot: ["dashdot", "dash-dot", "dash."],
|
||||
speedtestTracker: ["speedtest-tracker"],
|
||||
searchCh: ["search-ch"],
|
||||
gitHubContainerRegistry: ["ghcr"],
|
||||
linuxServerIO: ["linuxserver"],
|
||||
coolify: ["coolify"],
|
||||
truenas: ["truenas"],
|
||||
};
|
||||
|
||||
export const matchIntegrationKind = (search: string): IntegrationKind | null => {
|
||||
const normalized = search.toLowerCase().trim();
|
||||
if (!normalized) return null;
|
||||
|
||||
for (const kind of objectKeys(integrationDefs)) {
|
||||
if (kind.toLowerCase() === normalized) return kind;
|
||||
if (integrationDefs[kind].name.toLowerCase() === normalized) return kind;
|
||||
}
|
||||
|
||||
for (const kind of objectKeys(integrationDefs)) {
|
||||
if (integrationIconSlugs[kind] === normalized) return kind;
|
||||
}
|
||||
|
||||
for (const [kind, aliases] of Object.entries(integrationAliases) as [IntegrationKind, readonly string[]][]) {
|
||||
if (aliases.some((alias) => alias === normalized)) return kind;
|
||||
}
|
||||
|
||||
for (const kind of objectKeys(integrationDefs)) {
|
||||
if (normalized.includes(kind.toLowerCase())) return kind;
|
||||
if (normalized.includes(integrationIconSlugs[kind])) return kind;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const notDockerDiscoverable = new Set<IntegrationKind>([
|
||||
"dockerHub",
|
||||
"github",
|
||||
"gitlab",
|
||||
"npm",
|
||||
"codeberg",
|
||||
"linuxServerIO",
|
||||
"gitHubContainerRegistry",
|
||||
"quay",
|
||||
"ical",
|
||||
"searchCh",
|
||||
"mock",
|
||||
]);
|
||||
|
||||
interface ContainerMatchInput {
|
||||
image: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
export const matchIntegrationKindFromContainer = (container: ContainerMatchInput): IntegrationKind | null => {
|
||||
const imageName = extractContainerImageName(container.image);
|
||||
const fromImage = matchIntegrationKind(imageName);
|
||||
if (fromImage && !notDockerDiscoverable.has(fromImage)) return fromImage;
|
||||
|
||||
const fromName = matchIntegrationKind(container.name);
|
||||
if (fromName && !notDockerDiscoverable.has(fromName)) return fromName;
|
||||
|
||||
return null;
|
||||
};
|
||||
Reference in new issue
Block a user