Merge branch 'dev' into feat/openwebui-integration
Resolve conflicts by keeping both openWebUi and dev-side registry entries (integration/widget kinds, creators, docs sitemap). Take dev's next.config turbopack settings. Reset SQLite migration base to dev's 0040_add_widget_secret; the integration.creator_id migrations are regenerated for all dialects in a follow-up commit.
This commit is contained in:
517 files changed
+30974
-14645
No files matched your search
@@ -31,11 +31,11 @@ const integrationAliases: Partial<Record<IntegrationKind, readonly string[]>> =
|
||||
audiobookshelf: ["audiobookshelf"],
|
||||
navidrome: ["navidrome"],
|
||||
paperlessNgx: ["paperless-ngx", "paperless"],
|
||||
searchCh: ["search-ch"],
|
||||
gitHubContainerRegistry: ["ghcr"],
|
||||
linuxServerIO: ["linuxserver"],
|
||||
patchmon: ["patchmon", "patch-mon"],
|
||||
coolify: ["coolify"],
|
||||
truenas: ["truenas"],
|
||||
bazarr: ["bazarr"],
|
||||
synology: ["synology", "diskstation"],
|
||||
};
|
||||
|
||||
export const matchIntegrationKind = (search: string): IntegrationKind | null => {
|
||||
@@ -63,19 +63,7 @@ export const matchIntegrationKind = (search: string): IntegrationKind | null =>
|
||||
return null;
|
||||
};
|
||||
|
||||
const notDockerDiscoverable = new Set<IntegrationKind>([
|
||||
"dockerHub",
|
||||
"github",
|
||||
"gitlab",
|
||||
"npm",
|
||||
"codeberg",
|
||||
"linuxServerIO",
|
||||
"gitHubContainerRegistry",
|
||||
"quay",
|
||||
"ical",
|
||||
"searchCh",
|
||||
"mock",
|
||||
]);
|
||||
const notDockerDiscoverable = new Set<IntegrationKind>(["ical", "mock"]);
|
||||
|
||||
interface ContainerMatchInput {
|
||||
image: string;
|
||||
|
||||
@@ -60,8 +60,8 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/connections"
|
||||
| "/docs/tags/custom-widgets"
|
||||
| "/docs/tags/customization"
|
||||
| "/docs/tags/data-sources"
|
||||
| "/docs/tags/data"
|
||||
| "/docs/tags/data-sources"
|
||||
| "/docs/tags/database"
|
||||
| "/docs/tags/developer"
|
||||
| "/docs/tags/development"
|
||||
@@ -99,8 +99,8 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/tags/redis"
|
||||
| "/docs/tags/responsive"
|
||||
| "/docs/tags/roles"
|
||||
| "/docs/tags/search-engines"
|
||||
| "/docs/tags/search"
|
||||
| "/docs/tags/search-engines"
|
||||
| "/docs/tags/secrets"
|
||||
| "/docs/tags/security"
|
||||
| "/docs/tags/self-signed"
|
||||
@@ -132,15 +132,6 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/advanced/running-as-different-user"
|
||||
| "/docs/advanced/single-sign-on"
|
||||
| "/docs/advanced/styling"
|
||||
| "/docs/category/advanced"
|
||||
| "/docs/category/community"
|
||||
| "/docs/category/developer-guides"
|
||||
| "/docs/category/getting-started"
|
||||
| "/docs/category/installation-1"
|
||||
| "/docs/category/installation"
|
||||
| "/docs/category/integrations"
|
||||
| "/docs/category/management"
|
||||
| "/docs/category/widgets"
|
||||
| "/docs/community/donate"
|
||||
| "/docs/community/faq"
|
||||
| "/docs/community/get-in-touch"
|
||||
@@ -168,17 +159,13 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/archiveteam-warrior"
|
||||
| "/docs/integrations/aria2"
|
||||
| "/docs/integrations/audiobookshelf"
|
||||
| "/docs/integrations/bazarr"
|
||||
| "/docs/integrations/beszel"
|
||||
| "/docs/integrations/codeberg"
|
||||
| "/docs/integrations/coolify"
|
||||
| "/docs/integrations/dash-dot"
|
||||
| "/docs/integrations/deluge"
|
||||
| "/docs/integrations/docker-hub"
|
||||
| "/docs/integrations/docker"
|
||||
| "/docs/integrations/emby"
|
||||
| "/docs/integrations/github-containerregistry"
|
||||
| "/docs/integrations/github"
|
||||
| "/docs/integrations/gitlab"
|
||||
| "/docs/integrations/glances"
|
||||
| "/docs/integrations/gluetun"
|
||||
| "/docs/integrations/gotify"
|
||||
@@ -189,34 +176,33 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/jellyseerr"
|
||||
| "/docs/integrations/kubernetes"
|
||||
| "/docs/integrations/lidarr"
|
||||
| "/docs/integrations/linux-server-io"
|
||||
| "/docs/integrations/navidrome"
|
||||
| "/docs/integrations/nextcloud"
|
||||
| "/docs/integrations/npm"
|
||||
| "/docs/integrations/ntfy"
|
||||
| "/docs/integrations/nzbget"
|
||||
| "/docs/integrations/open-media-vault"
|
||||
| "/docs/integrations/opnsense"
|
||||
| "/docs/integrations/overseerr"
|
||||
| "/docs/integrations/paperless-ngx"
|
||||
| "/docs/integrations/patchmon"
|
||||
| "/docs/integrations/peanut"
|
||||
| "/docs/integrations/pi-hole"
|
||||
| "/docs/integrations/plex"
|
||||
| "/docs/integrations/prowlarr"
|
||||
| "/docs/integrations/proxmox"
|
||||
| "/docs/integrations/q-bittorent"
|
||||
| "/docs/integrations/quay"
|
||||
| "/docs/integrations/radarr"
|
||||
| "/docs/integrations/readarr"
|
||||
| "/docs/integrations/sabnzbd"
|
||||
| "/docs/integrations/search-ch"
|
||||
| "/docs/integrations/seerr"
|
||||
| "/docs/integrations/slskd"
|
||||
| "/docs/integrations/sonarr"
|
||||
| "/docs/integrations/speedtest-tracker"
|
||||
| "/docs/integrations/synology"
|
||||
| "/docs/integrations/tdarr"
|
||||
| "/docs/integrations/technitium-dns"
|
||||
| "/docs/integrations/tracearr"
|
||||
| "/docs/integrations/traefik"
|
||||
| "/docs/integrations/transmission"
|
||||
| "/docs/integrations/truenas"
|
||||
| "/docs/integrations/umami"
|
||||
@@ -239,6 +225,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/anchor-note"
|
||||
| "/docs/widgets/app"
|
||||
| "/docs/widgets/audio-stats"
|
||||
| "/docs/widgets/bazarr"
|
||||
| "/docs/widgets/beszel-alerts"
|
||||
| "/docs/widgets/beszel-system-grid"
|
||||
| "/docs/widgets/beszel-system-stats"
|
||||
@@ -258,6 +245,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/immich-album-carousel"
|
||||
| "/docs/widgets/immich-server-stats"
|
||||
| "/docs/widgets/indexer-manager"
|
||||
| "/docs/widgets/media-missing"
|
||||
| "/docs/widgets/media-releases"
|
||||
| "/docs/widgets/media-request-list"
|
||||
| "/docs/widgets/media-request-stats"
|
||||
@@ -269,15 +257,18 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/notebook"
|
||||
| "/docs/widgets/notifications"
|
||||
| "/docs/widgets/paperless-ngx"
|
||||
| "/docs/widgets/patchmon"
|
||||
| "/docs/widgets/releases"
|
||||
| "/docs/widgets/rss-feed"
|
||||
| "/docs/widgets/smart-home-entity-state"
|
||||
| "/docs/widgets/smart-home-execute-automation"
|
||||
| "/docs/widgets/speedtest-tracker"
|
||||
| "/docs/widgets/stock-price"
|
||||
| "/docs/widgets/system-disks"
|
||||
| "/docs/widgets/system-resources"
|
||||
| "/docs/widgets/timetable"
|
||||
| "/docs/widgets/tracearr"
|
||||
| "/docs/widgets/traefik"
|
||||
| "/docs/widgets/umami"
|
||||
| "/docs/widgets/ups"
|
||||
| "/docs/widgets/uptime-kuma"
|
||||
@@ -298,6 +289,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/lidarr"
|
||||
| "/docs/integrations/readarr"
|
||||
| "/docs/integrations/prowlarr"
|
||||
| "/docs/integrations/bazarr"
|
||||
| "/docs/integrations/jellyfin"
|
||||
| "/docs/integrations/emby"
|
||||
| "/docs/integrations/plex"
|
||||
@@ -316,24 +308,17 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/nextcloud"
|
||||
| "/docs/integrations/unifi-controller"
|
||||
| "/docs/integrations/opnsense"
|
||||
| "/docs/integrations/github"
|
||||
| "/docs/integrations/docker-hub"
|
||||
| "/docs/integrations/gitlab"
|
||||
| "/docs/integrations/npm"
|
||||
| "/docs/integrations/codeberg"
|
||||
| "/docs/integrations/linux-server-io"
|
||||
| "/docs/integrations/github-containerregistry"
|
||||
| "/docs/integrations/quay"
|
||||
| "/docs/integrations/ntfy"
|
||||
| "/docs/integrations/gotify"
|
||||
| "/docs/integrations/ical"
|
||||
| "/docs/integrations/anchor"
|
||||
| "/docs/integrations/truenas"
|
||||
| "/docs/integrations/synology"
|
||||
| "/docs/integrations/unraid"
|
||||
| "/docs/integrations/coolify"
|
||||
| "/docs/integrations/search-ch"
|
||||
| "/docs/integrations/immich"
|
||||
| "/docs/integrations/paperless-ngx"
|
||||
| "/docs/integrations/patchmon"
|
||||
| "/docs/integrations/tracearr"
|
||||
| "/docs/integrations/speedtest-tracker"
|
||||
| "/docs/integrations/uptime-kuma"
|
||||
@@ -344,6 +329,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/integrations/peanut"
|
||||
| "/docs/integrations/beszel"
|
||||
| "/docs/integrations/open-webui"
|
||||
| "/docs/integrations/traefik"
|
||||
| "/docs/widgets/clock"
|
||||
| "/docs/widgets/weather"
|
||||
| "/docs/widgets/app"
|
||||
@@ -362,6 +348,7 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/media-request-list"
|
||||
| "/docs/widgets/media-request-stats"
|
||||
| "/docs/widgets/media-transcoding"
|
||||
| "/docs/widgets/media-missing"
|
||||
| "/docs/widgets/minecraft-server-status"
|
||||
| "/docs/widgets/network-controller-summary"
|
||||
| "/docs/widgets/network-controller-status"
|
||||
@@ -376,10 +363,13 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/notifications"
|
||||
| "/docs/widgets/system-resources"
|
||||
| "/docs/widgets/coolify"
|
||||
| "/docs/widgets/system-disks"
|
||||
| "/docs/widgets/timetable"
|
||||
| "/docs/widgets/immich-server-stats"
|
||||
| "/docs/widgets/immich-album-carousel"
|
||||
| "/docs/widgets/paperless-ngx"
|
||||
| "/docs/widgets/patchmon"
|
||||
| "/docs/widgets/bazarr"
|
||||
| "/docs/widgets/tracearr"
|
||||
| "/docs/widgets/speedtest-tracker"
|
||||
| "/docs/widgets/uptime-kuma"
|
||||
@@ -391,5 +381,6 @@ export type HomarrDocumentationPath =
|
||||
| "/docs/widgets/beszel-system-grid"
|
||||
| "/docs/widgets/beszel-alerts"
|
||||
| "/docs/widgets/beszel-system-stats"
|
||||
| "/docs/widgets/traefik"
|
||||
| "/docs/widgets/custom-api"
|
||||
| "/docs/widgets/open-webui";
|
||||
@@ -13,6 +13,7 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
||||
lidarr: "lidarr",
|
||||
readarr: "readarr",
|
||||
prowlarr: "prowlarr",
|
||||
bazarr: "bazarr",
|
||||
jellyfin: "jellyfin",
|
||||
emby: "emby",
|
||||
plex: "plex",
|
||||
@@ -31,24 +32,17 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
||||
nextcloud: "nextcloud",
|
||||
unifiController: "unifi-controller",
|
||||
opnsense: "opnsense",
|
||||
github: "github",
|
||||
dockerHub: "docker-hub",
|
||||
gitlab: "gitlab",
|
||||
npm: "npm",
|
||||
codeberg: "codeberg",
|
||||
linuxServerIO: "linux-server-io",
|
||||
gitHubContainerRegistry: "github-containerregistry",
|
||||
quay: "quay",
|
||||
ntfy: "ntfy",
|
||||
gotify: "gotify",
|
||||
ical: "ical",
|
||||
anchor: "anchor",
|
||||
truenas: "truenas",
|
||||
synology: "synology",
|
||||
unraid: "unraid",
|
||||
coolify: "coolify",
|
||||
searchCh: "search-ch",
|
||||
immich: "immich",
|
||||
paperlessNgx: "paperless-ngx",
|
||||
patchmon: "patchmon",
|
||||
tracearr: "tracearr",
|
||||
speedtestTracker: "speedtest-tracker",
|
||||
uptimeKuma: "uptime-kuma",
|
||||
@@ -58,6 +52,7 @@ export const integrationDocSlugs: Record<IntegrationKind, string | null> = {
|
||||
gluetun: "gluetun",
|
||||
peaNut: "peanut",
|
||||
beszel: "beszel",
|
||||
traefik: "traefik",
|
||||
archiveTeamWarrior: null,
|
||||
openWebUi: "open-webui",
|
||||
mock: null,
|
||||
|
||||
@@ -19,6 +19,7 @@ export const widgetDocSlugs: Record<WidgetKind, string | null> = {
|
||||
"mediaRequests-requestList": "media-request-list",
|
||||
"mediaRequests-requestStats": "media-request-stats",
|
||||
mediaTranscoding: "media-transcoding",
|
||||
mediaMissing: "media-missing",
|
||||
minecraftServerStatus: "minecraft-server-status",
|
||||
networkControllerSummary: "network-controller-summary",
|
||||
networkControllerStatus: "network-controller-status",
|
||||
@@ -33,11 +34,13 @@ export const widgetDocSlugs: Record<WidgetKind, string | null> = {
|
||||
notifications: "notifications",
|
||||
systemResources: "system-resources",
|
||||
coolify: "coolify",
|
||||
systemDisks: null,
|
||||
systemDisks: "system-disks",
|
||||
timetable: "timetable",
|
||||
"immich-serverStats": "immich-server-stats",
|
||||
"immich-albumCarousel": "immich-album-carousel",
|
||||
paperlessNgx: "paperless-ngx",
|
||||
patchmon: "patchmon",
|
||||
bazarr: "bazarr",
|
||||
tracearr: "tracearr",
|
||||
speedtestTracker: "speedtest-tracker",
|
||||
uptimeKuma: "uptime-kuma",
|
||||
@@ -50,6 +53,7 @@ export const widgetDocSlugs: Record<WidgetKind, string | null> = {
|
||||
beszelSystemGrid: "beszel-system-grid",
|
||||
beszelAlerts: "beszel-alerts",
|
||||
beszelSystemStats: "beszel-system-stats",
|
||||
traefik: "traefik",
|
||||
customApi: "custom-api",
|
||||
openWebUi: "open-webui",
|
||||
};
|
||||
@@ -17,3 +17,4 @@ export * from "./emptysuperjson";
|
||||
export * from "./hotkeys";
|
||||
export * from "./docker-integration-match";
|
||||
export * from "./integration-url-template";
|
||||
export * from "./release-provider";
|
||||
@@ -13,6 +13,8 @@ export const integrationSecretKindObject = {
|
||||
topic: { isPublic: true, multiline: false },
|
||||
opnsenseApiKey: { isPublic: false, multiline: false },
|
||||
opnsenseApiSecret: { isPublic: false, multiline: false },
|
||||
patchmonApiKey: { isPublic: true, multiline: false },
|
||||
patchmonApiSecret: { isPublic: false, multiline: false },
|
||||
url: { isPublic: false, multiline: false },
|
||||
privateKey: { isPublic: false, multiline: true },
|
||||
githubAppId: { isPublic: true, multiline: false },
|
||||
@@ -96,7 +98,7 @@ export const integrationDefs = {
|
||||
name: "Sonarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/sonarr.svg",
|
||||
category: ["calendar"],
|
||||
category: ["calendar", "mediaOrganizer"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/sonarr"),
|
||||
defaultPort: 8989,
|
||||
apiKeySettingsPath: "/settings/general",
|
||||
@@ -105,7 +107,7 @@ export const integrationDefs = {
|
||||
name: "Radarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/radarr.svg",
|
||||
category: ["calendar"],
|
||||
category: ["calendar", "mediaOrganizer"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/radarr"),
|
||||
defaultPort: 7878,
|
||||
apiKeySettingsPath: "/settings/general",
|
||||
@@ -137,6 +139,15 @@ export const integrationDefs = {
|
||||
defaultPort: 9696,
|
||||
apiKeySettingsPath: "/settings/general",
|
||||
},
|
||||
bazarr: {
|
||||
name: "Bazarr",
|
||||
secretKinds: [["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/bazarr.svg",
|
||||
category: ["subtitleManager"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/bazarr"),
|
||||
defaultPort: 6767,
|
||||
apiKeySettingsPath: "/settings/general",
|
||||
},
|
||||
jellyfin: {
|
||||
name: "Jellyfin",
|
||||
secretKinds: [["username", "password"], ["apiKey"]],
|
||||
@@ -283,70 +294,6 @@ export const integrationDefs = {
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/opnsense"),
|
||||
defaultPort: 443,
|
||||
},
|
||||
github: {
|
||||
name: "Github",
|
||||
secretKinds: [[], ["personalAccessToken"], ["githubAppId", "githubInstallationId", "privateKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/github.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://api.github.com",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/github"),
|
||||
},
|
||||
dockerHub: {
|
||||
name: "Docker Hub",
|
||||
secretKinds: [[], ["username", "personalAccessToken"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/docker.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://hub.docker.com",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/docker-hub"),
|
||||
},
|
||||
gitlab: {
|
||||
name: "Gitlab",
|
||||
secretKinds: [[], ["personalAccessToken"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/gitlab.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://gitlab.com",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/gitlab"),
|
||||
},
|
||||
npm: {
|
||||
name: "NPM",
|
||||
secretKinds: [[]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/npm.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://registry.npmjs.org",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/npm"),
|
||||
},
|
||||
codeberg: {
|
||||
name: "Codeberg",
|
||||
secretKinds: [[], ["personalAccessToken"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/codeberg.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://codeberg.org",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/codeberg"),
|
||||
},
|
||||
linuxServerIO: {
|
||||
name: "LinuxServer.io",
|
||||
secretKinds: [[]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/linuxserver-io.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://api.linuxserver.io",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/linux-server-io"),
|
||||
},
|
||||
gitHubContainerRegistry: {
|
||||
name: "GitHub Container Registry",
|
||||
secretKinds: [[], ["personalAccessToken"], ["githubAppId", "githubInstallationId", "privateKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/github.svg",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://api.github.com",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/github"),
|
||||
},
|
||||
quay: {
|
||||
name: "Quay",
|
||||
secretKinds: [[], ["personalAccessToken"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/quay.png",
|
||||
category: ["releasesProvider"],
|
||||
defaultUrl: "https://quay.io",
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/quay"),
|
||||
},
|
||||
ntfy: {
|
||||
name: "ntfy",
|
||||
secretKinds: [["topic"], ["topic", "apiKey"]],
|
||||
@@ -385,6 +332,14 @@ export const integrationDefs = {
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/truenas"),
|
||||
defaultPort: 80,
|
||||
},
|
||||
synology: {
|
||||
name: "Synology DiskStation",
|
||||
secretKinds: [["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/synology.svg",
|
||||
category: ["healthMonitoring"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/synology"),
|
||||
defaultPort: 5000,
|
||||
},
|
||||
unraid: {
|
||||
name: "Unraid",
|
||||
secretKinds: [["apiKey"]],
|
||||
@@ -401,13 +356,6 @@ export const integrationDefs = {
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/coolify"),
|
||||
defaultPort: 8000,
|
||||
},
|
||||
searchCh: {
|
||||
name: "Search.ch",
|
||||
secretKinds: [[]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/png/search-ch.png",
|
||||
category: ["timetable"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/search-ch"),
|
||||
},
|
||||
immich: {
|
||||
name: "Immich",
|
||||
secretKinds: [["apiKey"]],
|
||||
@@ -424,6 +372,15 @@ export const integrationDefs = {
|
||||
documentationUrl: null,
|
||||
defaultPort: 8000,
|
||||
},
|
||||
patchmon: {
|
||||
name: "PatchMon",
|
||||
secretKinds: [["patchmonApiKey", "patchmonApiSecret"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/patchmon.svg",
|
||||
category: ["healthMonitoring"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/patchmon"),
|
||||
defaultPort: 3413,
|
||||
apiKeySettingsPath: "/settings/api-keys",
|
||||
},
|
||||
tracearr: {
|
||||
name: "Tracearr",
|
||||
secretKinds: [["apiKey"]],
|
||||
@@ -496,13 +453,21 @@ export const integrationDefs = {
|
||||
category: ["vpn"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/gluetun"),
|
||||
},
|
||||
traefik: {
|
||||
name: "Traefik",
|
||||
secretKinds: [[], ["username", "password"], ["apiKey"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/traefik.svg",
|
||||
category: ["reverseProxy"],
|
||||
documentationUrl: createDocumentationLink("/docs/integrations/traefik"),
|
||||
defaultPort: 8080,
|
||||
},
|
||||
archiveTeamWarrior: {
|
||||
name: "ArchiveTeam Warrior",
|
||||
secretKinds: [[], ["username", "password"]],
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/selfhst/icons/png/archiveteam-warrior.png",
|
||||
category: ["archiving"],
|
||||
defaultUrl: "http://localhost:8001",
|
||||
documentationUrl: null,
|
||||
defaultUrl: "http://localhost:8001",
|
||||
},
|
||||
openWebUi: {
|
||||
name: "Open WebUI",
|
||||
@@ -533,6 +498,7 @@ export const integrationDefs = {
|
||||
"smartHomeServer",
|
||||
"ups",
|
||||
"uptimeMonitoring",
|
||||
"mediaOrganizer",
|
||||
],
|
||||
documentationUrl: null,
|
||||
},
|
||||
@@ -598,6 +564,7 @@ export const integrationCategories = [
|
||||
"dnsHole",
|
||||
"mediaService",
|
||||
"calendar",
|
||||
"mediaOrganizer",
|
||||
"mediaSearch",
|
||||
"mediaRelease",
|
||||
"mediaRequest",
|
||||
@@ -611,7 +578,6 @@ export const integrationCategories = [
|
||||
"search",
|
||||
"mediaTranscoding",
|
||||
"networkController",
|
||||
"releasesProvider",
|
||||
"notifications",
|
||||
"firewall",
|
||||
"timetable",
|
||||
@@ -627,6 +593,8 @@ export const integrationCategories = [
|
||||
"mediaLibrary",
|
||||
"uptimeMonitoring",
|
||||
"ai",
|
||||
"subtitleManager",
|
||||
"reverseProxy",
|
||||
] as const;
|
||||
|
||||
export type IntegrationCategory = (typeof integrationCategories)[number];
|
||||
@@ -0,0 +1,78 @@
|
||||
import { objectKeys } from "@homarr/common";
|
||||
|
||||
export const releaseProviderDefs = {
|
||||
github: {
|
||||
name: "Github",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/github.svg",
|
||||
defaultUrl: "https://api.github.com",
|
||||
},
|
||||
dockerHub: {
|
||||
name: "Docker Hub",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/docker.svg",
|
||||
defaultUrl: "https://hub.docker.com",
|
||||
},
|
||||
gitlab: {
|
||||
name: "Gitlab",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/gitlab.svg",
|
||||
defaultUrl: "https://gitlab.com",
|
||||
},
|
||||
npm: {
|
||||
name: "NPM",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/npm.svg",
|
||||
defaultUrl: "https://registry.npmjs.org",
|
||||
},
|
||||
codeberg: {
|
||||
name: "Codeberg",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/codeberg.svg",
|
||||
defaultUrl: "https://codeberg.org",
|
||||
},
|
||||
linuxServerIO: {
|
||||
name: "LinuxServer.io",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/linuxserver-io.svg",
|
||||
defaultUrl: "https://api.linuxserver.io",
|
||||
},
|
||||
gitHubContainerRegistry: {
|
||||
name: "GitHub Container Registry",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/github.svg",
|
||||
defaultUrl: "https://ghcr.io",
|
||||
},
|
||||
quay: {
|
||||
name: "Quay",
|
||||
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/png/quay.png",
|
||||
defaultUrl: "https://quay.io",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const releaseProviderKinds = objectKeys(releaseProviderDefs);
|
||||
export type ReleaseProviderKind = keyof typeof releaseProviderDefs;
|
||||
|
||||
export const getReleaseProviderName = (provider: ReleaseProviderKind) => releaseProviderDefs[provider].name;
|
||||
export const getReleaseProviderIconUrl = (provider: ReleaseProviderKind) => releaseProviderDefs[provider].iconUrl;
|
||||
export const getReleaseProviderDefaultUrl = (provider: ReleaseProviderKind) => releaseProviderDefs[provider].defaultUrl;
|
||||
|
||||
const releaseProviderRegistryPrefixes: Partial<Record<ReleaseProviderKind, string>> = {
|
||||
dockerHub: "docker.io/",
|
||||
gitHubContainerRegistry: "ghcr.io/",
|
||||
linuxServerIO: "lscr.io/",
|
||||
quay: "quay.io/",
|
||||
};
|
||||
|
||||
const removeContainerImageVersion = (identifier: string) => {
|
||||
const digestIndex = identifier.indexOf("@");
|
||||
const withoutDigest = digestIndex === -1 ? identifier : identifier.slice(0, digestIndex);
|
||||
const tagIndex = withoutDigest.indexOf(":", withoutDigest.lastIndexOf("/") + 1);
|
||||
|
||||
return tagIndex === -1 ? withoutDigest : withoutDigest.slice(0, tagIndex);
|
||||
};
|
||||
|
||||
export const normalizeReleaseProviderIdentifier = (provider: ReleaseProviderKind, identifier: string) => {
|
||||
const trimmedIdentifier = identifier.trim();
|
||||
const registryPrefix = releaseProviderRegistryPrefixes[provider];
|
||||
const withoutRegistry =
|
||||
registryPrefix && trimmedIdentifier.startsWith(registryPrefix)
|
||||
? trimmedIdentifier.slice(registryPrefix.length)
|
||||
: trimmedIdentifier;
|
||||
|
||||
// ponytail: only strip container image versions/digests for providers that use them
|
||||
return registryPrefix ? removeContainerImageVersion(withoutRegistry) : withoutRegistry;
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import { normalizeReleaseProviderIdentifier } from "../release-provider";
|
||||
|
||||
describe("normalizeReleaseProviderIdentifier", () => {
|
||||
it("normalizes full ghcr image references", () => {
|
||||
expect(normalizeReleaseProviderIdentifier("gitHubContainerRegistry", "ghcr.io/muchobien/pocketbase:latest")).toBe(
|
||||
"muchobien/pocketbase",
|
||||
);
|
||||
expect(normalizeReleaseProviderIdentifier("gitHubContainerRegistry", "ghcr.io/homarr-labs/homarr:latest")).toBe(
|
||||
"homarr-labs/homarr",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps existing ghcr owner/name identifiers unchanged", () => {
|
||||
expect(normalizeReleaseProviderIdentifier("gitHubContainerRegistry", "homarr-labs/homarr")).toBe(
|
||||
"homarr-labs/homarr",
|
||||
);
|
||||
});
|
||||
|
||||
it("normalizes container image identifiers for other registries", () => {
|
||||
expect(normalizeReleaseProviderIdentifier("dockerHub", "postgres:17")).toBe("postgres");
|
||||
expect(normalizeReleaseProviderIdentifier("dockerHub", "docker.io/library/postgres:17")).toBe("library/postgres");
|
||||
expect(normalizeReleaseProviderIdentifier("dockerHub", "library/postgres@sha256:abc123")).toBe("library/postgres");
|
||||
expect(normalizeReleaseProviderIdentifier("linuxServerIO", "lscr.io/linuxserver/radarr:latest")).toBe(
|
||||
"linuxserver/radarr",
|
||||
);
|
||||
expect(normalizeReleaseProviderIdentifier("quay", "quay.io/prometheus/prometheus:v3.0.0")).toBe(
|
||||
"prometheus/prometheus",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -20,27 +20,31 @@ export const widgetIntegrationSupport: Partial<Record<WidgetKind, readonly Integ
|
||||
"mediaRequests-requestList": getIntegrationKindsByCategory("mediaRequest"),
|
||||
"mediaRequests-requestStats": getIntegrationKindsByCategory("mediaRequest"),
|
||||
mediaTranscoding: getIntegrationKindsByCategory("mediaTranscoding"),
|
||||
mediaMissing: getIntegrationKindsByCategory("mediaOrganizer"),
|
||||
networkControllerSummary: getIntegrationKindsByCategory("networkController"),
|
||||
networkControllerStatus: getIntegrationKindsByCategory("networkController"),
|
||||
indexerManager: getIntegrationKindsByCategory("indexerManager"),
|
||||
healthMonitoring: getIntegrationKindsByCategory("healthMonitoring"),
|
||||
healthMonitoring: getIntegrationKindsByCategory("healthMonitoring").filter((kind) => kind !== "patchmon"),
|
||||
firewall: getIntegrationKindsByCategory("firewall"),
|
||||
notifications: getIntegrationKindsByCategory("notifications"),
|
||||
mediaReleases: ["emby", "jellyfin", "plex"],
|
||||
systemResources: ["dashDot", "openmediavault", "truenas", "unraid", "glances"],
|
||||
systemDisks: ["dashDot", "openmediavault", "truenas", "unraid"],
|
||||
systemResources: ["dashDot", "openmediavault", "truenas", "unraid", "glances", "synology"],
|
||||
systemDisks: ["dashDot", "openmediavault", "truenas", "unraid", "synology"],
|
||||
coolify: ["coolify"],
|
||||
timetable: ["searchCh"],
|
||||
"immich-serverStats": ["immich"],
|
||||
"immich-albumCarousel": ["immich"],
|
||||
paperlessNgx: ["paperlessNgx"],
|
||||
patchmon: ["patchmon"],
|
||||
bazarr: ["bazarr"],
|
||||
tracearr: ["tracearr"],
|
||||
speedtestTracker: ["speedtestTracker"],
|
||||
uptimeKuma: ["uptimeKuma"],
|
||||
audioStats: ["navidrome", "audiobookshelf"],
|
||||
vpn: getIntegrationKindsByCategory("vpn"),
|
||||
archiveTeamWarrior: ["archiveTeamWarrior"],
|
||||
anchorNote: ["anchor"],
|
||||
openWebUi: ["openWebUi"],
|
||||
traefik: ["traefik"],
|
||||
};
|
||||
|
||||
export const getWidgetKindsForIntegration = (integrationKind: IntegrationKind): WidgetKind[] => {
|
||||
@@ -81,18 +85,7 @@ export const featuredIntegrations: readonly IntegrationKind[] = [
|
||||
"jellyfin",
|
||||
];
|
||||
|
||||
export const hiddenFromOnboarding = new Set<IntegrationKind>([
|
||||
"searchCh",
|
||||
"github",
|
||||
"dockerHub",
|
||||
"gitlab",
|
||||
"npm",
|
||||
"codeberg",
|
||||
"linuxServerIO",
|
||||
"gitHubContainerRegistry",
|
||||
"quay",
|
||||
"mock",
|
||||
]);
|
||||
export const hiddenFromOnboarding = new Set<IntegrationKind>(["mock"]);
|
||||
|
||||
export const defaultBookmarkApps = [
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ export const widgetKinds = [
|
||||
"mediaRequests-requestList",
|
||||
"mediaRequests-requestStats",
|
||||
"mediaTranscoding",
|
||||
"mediaMissing",
|
||||
"minecraftServerStatus",
|
||||
"networkControllerSummary",
|
||||
"networkControllerStatus",
|
||||
@@ -36,6 +37,8 @@ export const widgetKinds = [
|
||||
"immich-serverStats",
|
||||
"immich-albumCarousel",
|
||||
"paperlessNgx",
|
||||
"patchmon",
|
||||
"bazarr",
|
||||
"tracearr",
|
||||
"speedtestTracker",
|
||||
"uptimeKuma",
|
||||
@@ -48,6 +51,7 @@ export const widgetKinds = [
|
||||
"beszelSystemGrid",
|
||||
"beszelAlerts",
|
||||
"beszelSystemStats",
|
||||
"traefik",
|
||||
"customApi",
|
||||
"openWebUi",
|
||||
] as const;
|
||||
@@ -57,4 +61,7 @@ export const widgetDefaultSizes: Partial<Record<WidgetKind, { width: number; hei
|
||||
uptimeKuma: { width: 2, height: 3 },
|
||||
audioStats: { width: 2, height: 2 },
|
||||
paperlessNgx: { width: 2, height: 2 },
|
||||
patchmon: { width: 2, height: 2 },
|
||||
mediaMissing: { width: 4, height: 3 },
|
||||
bazarr: { width: 2, height: 2 },
|
||||
};
|
||||
Reference in new issue
Block a user