refactor: simplify widget and integration architecture

This commit is contained in:
ajnart committed 2026-08-24 00:57:36 +02:00
1 parent c988c35b29
commit 8f9efd0074
179 files changed
+1509 -4187

No files matched your search

+139 -175
View File
@@ -2,187 +2,128 @@ import type { IntegrationKind } from "@homarr/definitions";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
import { generatedIntegrationCreatorLoaders } from "../generated/integration-creators";
import type { Integration, IntegrationInput } from "./integration";
const logger = createLogger({ module: "integrationFactory" });
type IntegrationCreator<TIntegration extends Integration = Integration> = (
input: IntegrationInput,
) => Promise<TIntegration>;
type IntegrationConstructor<TIntegration extends Integration = Integration> = new (
input: IntegrationInput,
) => TIntegration;
const createConstructorCreator =
<TIntegration extends Integration>(
IntegrationClass: IntegrationConstructor<TIntegration>,
): IntegrationCreator<TIntegration> =>
async (input) =>
new IntegrationClass(input);
// Keep each import path explicit so Node and Turbopack can discover every lazy integration chunk.
const integrationCreatorLoaders = {
anchor: async () => createConstructorCreator((await import("../anchor/anchor-integration")).AnchorIntegration),
piHole: async () => (await import("../pi-hole/pi-hole-integration-factory")).createPiHoleIntegrationAsync,
adGuardHome: async () =>
createConstructorCreator((await import("../adguard-home/adguard-home-integration")).AdGuardHomeIntegration),
technitiumDns: async () =>
(await import("../technitium/technitium-integration-factory")).createTechnitiumDnsIntegrationAsync,
homeAssistant: async () =>
createConstructorCreator((await import("../homeassistant/homeassistant-integration")).HomeAssistantIntegration),
jellyfin: async () =>
createConstructorCreator((await import("../jellyfin/jellyfin-integration")).JellyfinIntegration),
plex: async () => createConstructorCreator((await import("../plex/plex-integration")).PlexIntegration),
sonarr: async () =>
createConstructorCreator((await import("../media-organizer/sonarr/sonarr-integration")).SonarrIntegration),
radarr: async () =>
createConstructorCreator((await import("../media-organizer/radarr/radarr-integration")).RadarrIntegration),
sabNzbd: async () =>
createConstructorCreator((await import("../download-client/sabnzbd/sabnzbd-integration")).SabnzbdIntegration),
nzbGet: async () =>
createConstructorCreator((await import("../download-client/nzbget/nzbget-integration")).NzbGetIntegration),
qBittorrent: async () =>
createConstructorCreator(
(await import("../download-client/qbittorrent/qbittorrent-integration")).QBitTorrentIntegration,
),
deluge: async () =>
createConstructorCreator((await import("../download-client/deluge/deluge-integration")).DelugeIntegration),
transmission: async () =>
createConstructorCreator(
(await import("../download-client/transmission/transmission-integration")).TransmissionIntegration,
),
slskd: async () =>
createConstructorCreator((await import("../download-client/slskd/slskd-integration")).SlskdIntegration),
aria2: async () =>
createConstructorCreator((await import("../download-client/aria2/aria2-integration")).Aria2Integration),
jellyseerr: async () =>
createConstructorCreator((await import("../jellyseerr/jellyseerr-integration")).JellyseerrIntegration),
seerr: async () => createConstructorCreator((await import("../seerr/seerr-integration")).SeerrIntegration),
overseerr: async () =>
createConstructorCreator((await import("../overseerr/overseerr-integration")).OverseerrIntegration),
prowlarr: async () =>
createConstructorCreator((await import("../prowlarr/prowlarr-integration")).ProwlarrIntegration),
openmediavault: async () =>
createConstructorCreator((await import("../openmediavault/openmediavault-integration")).OpenMediaVaultIntegration),
lidarr: async () =>
createConstructorCreator((await import("../media-organizer/lidarr/lidarr-integration")).LidarrIntegration),
readarr: async () =>
createConstructorCreator((await import("../media-organizer/readarr/readarr-integration")).ReadarrIntegration),
dashDot: async () => createConstructorCreator((await import("../dashdot/dashdot-integration")).DashDotIntegration),
tdarr: async () =>
createConstructorCreator((await import("../media-transcoding/tdarr-integration")).TdarrIntegration),
proxmox: async () => createConstructorCreator((await import("../proxmox/proxmox-integration")).ProxmoxIntegration),
emby: async () => createConstructorCreator((await import("../emby/emby-integration")).EmbyIntegration),
nextcloud: async () =>
createConstructorCreator((await import("../nextcloud/nextcloud.integration")).NextcloudIntegration),
unifiController: async () =>
createConstructorCreator(
(await import("../unifi-controller/unifi-controller-integration")).UnifiControllerIntegration,
),
opnsense: async () =>
createConstructorCreator((await import("../opnsense/opnsense-integration")).OPNsenseIntegration),
ical: async () => createConstructorCreator((await import("../ical/ical-integration")).ICalIntegration),
ntfy: async () => createConstructorCreator((await import("../ntfy/ntfy-integration")).NTFYIntegration),
gotify: async () => createConstructorCreator((await import("../gotify/gotify-integration")).GotifyIntegration),
mock: async () => createConstructorCreator((await import("../mock/mock-integration")).MockIntegration),
truenas: async () => createConstructorCreator((await import("../truenas/truenas-integration")).TrueNasIntegration),
synology: async () =>
createConstructorCreator((await import("../synology/synology-integration")).SynologyIntegration),
unraid: async () => createConstructorCreator((await import("../unraid/unraid-integration")).UnraidIntegration),
coolify: async () => createConstructorCreator((await import("../coolify/coolify-integration")).CoolifyIntegration),
tracearr: async () =>
createConstructorCreator((await import("../tracearr/tracearr-integration")).TracearrIntegration),
glances: async () => createConstructorCreator((await import("../glances/glances-integration")).GlancesIntegration),
immich: async () => createConstructorCreator((await import("../immich/immich-integration")).ImmichIntegration),
paperlessNgx: async () =>
createConstructorCreator((await import("../paperless-ngx/paperless-ngx-integration")).PaperlessNgxIntegration),
patchmon: async () =>
createConstructorCreator((await import("../patchmon/patchmon-integration")).PatchMonIntegration),
speedtestTracker: async () =>
createConstructorCreator(
(await import("../speedtest-tracker/speedtest-tracker-integration")).SpeedtestTrackerIntegration,
),
audiobookshelf: async () =>
createConstructorCreator((await import("../audiobookshelf/audiobookshelf-integration")).AudiobookshelfIntegration),
navidrome: async () =>
createConstructorCreator((await import("../navidrome/navidrome-integration")).NavidromeIntegration),
umami: async () => createConstructorCreator((await import("../umami/umami-integration")).UmamiIntegration),
gluetun: async () => createConstructorCreator((await import("../gluetun/gluetun-integration")).GluetunIntegration),
archiveTeamWarrior: async () =>
createConstructorCreator(
(await import("../archive-team-warrior/archive-team-warrior-integration")).ArchiveTeamWarriorIntegration,
),
uptimeKuma: async () =>
createConstructorCreator((await import("../uptime-kuma/uptime-kuma-integration")).UptimeKumaIntegration),
peaNut: async () => createConstructorCreator((await import("../peanut/peanut-integration")).PeaNutIntegration),
...generatedIntegrationCreatorLoaders,
bazarr: async () => createConstructorCreator((await import("../bazarr/bazarr-integration")).BazarrIntegration),
traefik: async () => createConstructorCreator((await import("../traefik/traefik-integration")).TraefikIntegration),
wud: async () => createConstructorCreator((await import("../wud/wud-integration")).WudIntegration),
};
const integrationCreators = {
anchor: async (input: IntegrationInput) =>
new (await import("../anchor/anchor-integration")).AnchorIntegration(input),
piHole: async (input: IntegrationInput) =>
(await import("../pi-hole/pi-hole-integration-factory")).createPiHoleIntegrationAsync(input),
adGuardHome: async (input: IntegrationInput) =>
new (await import("../adguard-home/adguard-home-integration")).AdGuardHomeIntegration(input),
technitiumDns: async (input: IntegrationInput) =>
(await import("../technitium/technitium-integration-factory")).createTechnitiumDnsIntegrationAsync(input),
homeAssistant: async (input: IntegrationInput) =>
new (await import("../homeassistant/homeassistant-integration")).HomeAssistantIntegration(input),
jellyfin: async (input: IntegrationInput) =>
new (await import("../jellyfin/jellyfin-integration")).JellyfinIntegration(input),
plex: async (input: IntegrationInput) => new (await import("../plex/plex-integration")).PlexIntegration(input),
sonarr: async (input: IntegrationInput) =>
new (await import("../media-organizer/sonarr/sonarr-integration")).SonarrIntegration(input),
radarr: async (input: IntegrationInput) =>
new (await import("../media-organizer/radarr/radarr-integration")).RadarrIntegration(input),
sabNzbd: async (input: IntegrationInput) =>
new (await import("../download-client/sabnzbd/sabnzbd-integration")).SabnzbdIntegration(input),
nzbGet: async (input: IntegrationInput) =>
new (await import("../download-client/nzbget/nzbget-integration")).NzbGetIntegration(input),
qBittorrent: async (input: IntegrationInput) =>
new (await import("../download-client/qbittorrent/qbittorrent-integration")).QBitTorrentIntegration(input),
deluge: async (input: IntegrationInput) =>
new (await import("../download-client/deluge/deluge-integration")).DelugeIntegration(input),
transmission: async (input: IntegrationInput) =>
new (await import("../download-client/transmission/transmission-integration")).TransmissionIntegration(input),
slskd: async (input: IntegrationInput) =>
new (await import("../download-client/slskd/slskd-integration")).SlskdIntegration(input),
aria2: async (input: IntegrationInput) =>
new (await import("../download-client/aria2/aria2-integration")).Aria2Integration(input),
jellyseerr: async (input: IntegrationInput) =>
new (await import("../jellyseerr/jellyseerr-integration")).JellyseerrIntegration(input),
seerr: async (input: IntegrationInput) => new (await import("../seerr/seerr-integration")).SeerrIntegration(input),
overseerr: async (input: IntegrationInput) =>
new (await import("../overseerr/overseerr-integration")).OverseerrIntegration(input),
prowlarr: async (input: IntegrationInput) =>
new (await import("../prowlarr/prowlarr-integration")).ProwlarrIntegration(input),
openmediavault: async (input: IntegrationInput) =>
new (await import("../openmediavault/openmediavault-integration")).OpenMediaVaultIntegration(input),
lidarr: async (input: IntegrationInput) =>
new (await import("../media-organizer/lidarr/lidarr-integration")).LidarrIntegration(input),
readarr: async (input: IntegrationInput) =>
new (await import("../media-organizer/readarr/readarr-integration")).ReadarrIntegration(input),
dashDot: async (input: IntegrationInput) =>
new (await import("../dashdot/dashdot-integration")).DashDotIntegration(input),
tdarr: async (input: IntegrationInput) =>
new (await import("../media-transcoding/tdarr-integration")).TdarrIntegration(input),
proxmox: async (input: IntegrationInput) =>
new (await import("../proxmox/proxmox-integration")).ProxmoxIntegration(input),
emby: async (input: IntegrationInput) => new (await import("../emby/emby-integration")).EmbyIntegration(input),
nextcloud: async (input: IntegrationInput) =>
new (await import("../nextcloud/nextcloud.integration")).NextcloudIntegration(input),
unifiController: async (input: IntegrationInput) =>
new (await import("../unifi-controller/unifi-controller-integration")).UnifiControllerIntegration(input),
opnsense: async (input: IntegrationInput) =>
new (await import("../opnsense/opnsense-integration")).OPNsenseIntegration(input),
ical: async (input: IntegrationInput) => new (await import("../ical/ical-integration")).ICalIntegration(input),
ntfy: async (input: IntegrationInput) => new (await import("../ntfy/ntfy-integration")).NTFYIntegration(input),
gotify: async (input: IntegrationInput) =>
new (await import("../gotify/gotify-integration")).GotifyIntegration(input),
mock: async (input: IntegrationInput) => new (await import("../mock/mock-integration")).MockIntegration(input),
truenas: async (input: IntegrationInput) =>
new (await import("../truenas/truenas-integration")).TrueNasIntegration(input),
synology: async (input: IntegrationInput) =>
new (await import("../synology/synology-integration")).SynologyIntegration(input),
unraid: async (input: IntegrationInput) =>
new (await import("../unraid/unraid-integration")).UnraidIntegration(input),
coolify: async (input: IntegrationInput) =>
new (await import("../coolify/coolify-integration")).CoolifyIntegration(input),
tracearr: async (input: IntegrationInput) =>
new (await import("../tracearr/tracearr-integration")).TracearrIntegration(input),
glances: async (input: IntegrationInput) =>
new (await import("../glances/glances-integration")).GlancesIntegration(input),
immich: async (input: IntegrationInput) =>
new (await import("../immich/immich-integration")).ImmichIntegration(input),
paperlessNgx: async (input: IntegrationInput) =>
new (await import("../paperless-ngx/paperless-ngx-integration")).PaperlessNgxIntegration(input),
patchmon: async (input: IntegrationInput) =>
new (await import("../patchmon/patchmon-integration")).PatchMonIntegration(input),
speedtestTracker: async (input: IntegrationInput) =>
new (await import("../speedtest-tracker/speedtest-tracker-integration")).SpeedtestTrackerIntegration(input),
audiobookshelf: async (input: IntegrationInput) =>
new (await import("../audiobookshelf/audiobookshelf-integration")).AudiobookshelfIntegration(input),
navidrome: async (input: IntegrationInput) =>
new (await import("../navidrome/navidrome-integration")).NavidromeIntegration(input),
umami: async (input: IntegrationInput) => new (await import("../umami/umami-integration")).UmamiIntegration(input),
gluetun: async (input: IntegrationInput) =>
new (await import("../gluetun/gluetun-integration")).GluetunIntegration(input),
archiveTeamWarrior: async (input: IntegrationInput) =>
new (await import("../archive-team-warrior/archive-team-warrior-integration")).ArchiveTeamWarriorIntegration(input),
uptimeKuma: async (input: IntegrationInput) =>
new (await import("../uptime-kuma/uptime-kuma-integration")).UptimeKumaIntegration(input),
peaNut: async (input: IntegrationInput) =>
new (await import("../peanut/peanut-integration")).PeaNutIntegration(input),
beszel: async (input: IntegrationInput) =>
new (await import("../beszel/beszel-integration")).BeszelIntegration(input),
bazarr: async (input: IntegrationInput) =>
new (await import("../bazarr/bazarr-integration")).BazarrIntegration(input),
traefik: async (input: IntegrationInput) =>
new (await import("../traefik/traefik-integration")).TraefikIntegration(input),
wud: async (input: IntegrationInput) => new (await import("../wud/wud-integration")).WudIntegration(input),
} satisfies Record<IntegrationKind, (input: IntegrationInput) => Promise<Integration>>;
type AssertIntegrationCreatorLoaders<TLoaders extends Record<IntegrationKind, () => Promise<IntegrationCreator>>> =
TLoaders;
type AssertNoUnexpectedIntegrationKinds<TKind extends never> = TKind;
type IntegrationCreatorLoadersCheck = AssertIntegrationCreatorLoaders<typeof integrationCreatorLoaders>;
type UnexpectedIntegrationKindsCheck = AssertNoUnexpectedIntegrationKinds<
Exclude<keyof typeof integrationCreatorLoaders, IntegrationKind>
type IntegrationCreators = typeof integrationCreators;
type IntegrationInstanceOfKind<TKind extends keyof IntegrationCreators> = Awaited<
ReturnType<IntegrationCreators[TKind]>
>;
type IntegrationCreatorLoaders = IntegrationCreatorLoadersCheck & Record<UnexpectedIntegrationKindsCheck, never>;
type IntegrationCreatorOfKind<TKind extends keyof IntegrationCreatorLoaders> = Awaited<
ReturnType<IntegrationCreatorLoaders[TKind]>
>;
type IntegrationInstanceOfKind<TKind extends keyof IntegrationCreatorLoaders> = Awaited<
ReturnType<IntegrationCreatorOfKind<TKind>>
>;
const integrationCreatorCache = new Map<IntegrationKind, Promise<IntegrationCreator>>();
const loadIntegrationCreatorAsync = async <TKind extends keyof IntegrationCreatorLoaders>(
kind: TKind,
): Promise<IntegrationCreatorOfKind<TKind>> => {
const cachedCreator = integrationCreatorCache.get(kind);
if (cachedCreator) {
return (await cachedCreator) as IntegrationCreatorOfKind<TKind>;
}
const startedAt = Date.now();
logger.debug("Loading integration implementation", { integrationKind: kind });
const creatorPromise = integrationCreatorLoaders[kind]();
integrationCreatorCache.set(kind, creatorPromise);
try {
const creator = (await creatorPromise) as IntegrationCreatorOfKind<TKind>;
logger.debug("Integration implementation loaded", {
integrationKind: kind,
durationMs: Date.now() - startedAt,
});
return creator;
} catch (error) {
if (integrationCreatorCache.get(kind) === creatorPromise) {
integrationCreatorCache.delete(kind);
}
logger.warn(
new ErrorWithMetadata(
"Integration implementation failed to load",
{
integrationKind: kind,
durationMs: Date.now() - startedAt,
},
{ cause: error },
),
);
throw error;
}
};
export const createIntegrationAsync = async <TKind extends keyof IntegrationCreatorLoaders>(
export function createIntegrationAsync<TKind extends keyof IntegrationCreators>(
integration: IntegrationInput & { kind: TKind },
): Promise<IntegrationInstanceOfKind<TKind>> => {
if (!Object.hasOwn(integrationCreatorLoaders, integration.kind)) {
): Promise<IntegrationInstanceOfKind<TKind>>;
export async function createIntegrationAsync(
integration: IntegrationInput & { kind: IntegrationKind },
): Promise<Integration> {
if (!Object.hasOwn(integrationCreators, integration.kind)) {
logger.warn("Integration client creation refused", {
integrationId: integration.id,
integrationKind: integration.kind,
@@ -193,6 +134,29 @@ export const createIntegrationAsync = async <TKind extends keyof IntegrationCrea
);
}
const creator = await loadIntegrationCreatorAsync(integration.kind);
return (await creator(integration)) as IntegrationInstanceOfKind<TKind>;
};
const startedAt = Date.now();
logger.debug("Creating integration client", { integrationId: integration.id, integrationKind: integration.kind });
try {
const instance = await integrationCreators[integration.kind](integration);
logger.debug("Integration client created", {
integrationId: integration.id,
integrationKind: integration.kind,
durationMs: Date.now() - startedAt,
});
return instance;
} catch (error) {
logger.warn(
new ErrorWithMetadata(
"Integration client creation failed",
{
integrationId: integration.id,
integrationKind: integration.kind,
durationMs: Date.now() - startedAt,
},
{ cause: error },
),
);
throw error;
}
}
@@ -42,6 +42,12 @@ const createSafeErrorCause = (error: unknown, depth = 0): Error => {
if (error instanceof Error && safeErrorNameRegex.test(error.name)) {
safeError.name = error.name;
}
if (error instanceof Error && error.stack) {
const originalHeader = Error.prototype.toString.call(error);
if (error.stack.startsWith(originalHeader)) {
safeError.stack = `${safeError.name}: ${safeError.message}${error.stack.slice(originalHeader.length)}`;
}
}
return safeError;
};
@@ -3,12 +3,12 @@ import superjson from "superjson";
import { decryptSecret, encryptSecret } from "@homarr/common/server";
import { createLogger } from "@homarr/core/infrastructure/logs";
import { ErrorWithMetadata } from "@homarr/core/infrastructure/logs/error";
import { createGetSetChannel } from "@homarr/redis";
import { createGetSetChannel, getIntegrationSessionStoreKey } from "@homarr/redis";
const logger = createLogger({ module: "sessionStore" });
export const createSessionStore = <TValue>(integration: { id: string }) => {
const channelName = `session-store:${integration.id}`;
const channelName = getIntegrationSessionStoreKey(integration.id);
const channel = createGetSetChannel<`${string}.${string}`>(channelName);
return {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 948 KiB

@@ -1,58 +0,0 @@
---
title: "Beszel"
description: "Beszel is a lightweight server monitoring platform with Docker stats, historical data, and alert functions."
hide_title: true
---
import { IntegrationHeader } from "@site/src/components/integrations/header";
import { IntegrationCapabilites } from "@site/src/components/integrations/widgets";
import { AddingIntegration } from "@site/src/components/integrations/adding";
import { IntegrationSecrets } from "@site/src/components/integrations/secrets";
import { beszelIntegration } from ".";
import { beszelSystemStatsWidget } from "@site/docs/widgets/beszel-system-stats";
import { beszelSystemGridWidget } from "@site/docs/widgets/beszel-system-grid";
import { beszelSystemTableWidget } from "@site/docs/widgets/beszel-system-table";
import { beszelAlertsWidget } from "@site/docs/widgets/beszel-alerts";
import beszelDashboard from "./img/beszel-dashboard.png";
<IntegrationHeader integration={beszelIntegration} categories={["System Monitoring"]} />
Beszel monitors your servers in real time via lightweight agents, collecting CPU, memory, disk, network, GPU, temperature, and Docker container metrics. It stores historical data and supports configurable alerts.
### Screenshots
<img src={beszelDashboard} alt="Beszel dashboard overview showing all four widgets" />
### Widgets & Capabilities
<IntegrationCapabilites
items={[
{ widget: beszelSystemStatsWidget },
{ widget: beszelSystemGridWidget },
{ widget: beszelSystemTableWidget },
{ widget: beszelAlertsWidget },
]}
/>
### Adding the integration
<AddingIntegration />
### Secrets
<IntegrationSecrets
secrets={[
{
credentials: ["username", "password"],
steps: [
"Open your Beszel hub instance (default port 8090)",
"Use the same credentials you use to log in to the Beszel web UI",
],
},
]}
/>
:::tip
Beszel uses PocketBase under the hood. The default admin credentials are set during the initial Beszel setup.
:::
@@ -1,7 +0,0 @@
export const beszelIntegration = {
name: "Beszel",
description:
"Beszel is a lightweight server monitoring platform with Docker stats, historical data, and alert functions.",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/beszel.svg",
path: "../../integrations/beszel",
} as const;
@@ -1,19 +0,0 @@
import { defineIntegrationModule } from "@homarr/definitions";
export default defineIntegrationModule({
kind: "beszel",
name: "Beszel",
iconUrl: "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons@master/svg/beszel.svg",
secretKinds: [["username", "password"]],
categories: ["beszel"],
defaultPort: 8090,
documentation: {
slug: "beszel",
sourceDirectory: "docs",
},
creator: {
type: "constructor",
module: "./beszel-integration",
exportName: "BeszelIntegration",
},
});
@@ -1,12 +0,0 @@
// This file is generated by pnpm integrations:sync. Do not edit it directly.
import type { Integration, IntegrationInput } from "../base/integration";
type GeneratedIntegrationCreator = (input: IntegrationInput) => Promise<Integration>;
export const generatedIntegrationCreatorLoaders = {
beszel: async () => {
const IntegrationClass = (await import("../beszel/beszel-integration")).BeszelIntegration;
return async (input: IntegrationInput) => new IntegrationClass(input);
},
} satisfies Record<string, () => Promise<GeneratedIntegrationCreator>>;
+58 -7
View File
@@ -1,6 +1,53 @@
// Type-only compatibility surface. Runtime capabilities have explicit subpaths.
// General integrations
export { ArchiveTeamWarriorIntegration } from "./archive-team-warrior/archive-team-warrior-integration";
export { WudIntegration } from "./wud/wud-integration";
export { AdGuardHomeIntegration } from "./adguard-home/adguard-home-integration";
export { TechnitiumDnsIntegration } from "./technitium/technitium-integration";
export { AnchorIntegration } from "./anchor/anchor-integration";
export { Aria2Integration } from "./download-client/aria2/aria2-integration";
export { DelugeIntegration } from "./download-client/deluge/deluge-integration";
export { NzbGetIntegration } from "./download-client/nzbget/nzbget-integration";
export { QBitTorrentIntegration } from "./download-client/qbittorrent/qbittorrent-integration";
export { SabnzbdIntegration } from "./download-client/sabnzbd/sabnzbd-integration";
export { SlskdIntegration } from "./download-client/slskd/slskd-integration";
export { TransmissionIntegration } from "./download-client/transmission/transmission-integration";
export { HomeAssistantIntegration } from "./homeassistant/homeassistant-integration";
export { JellyfinIntegration } from "./jellyfin/jellyfin-integration";
export { JellyseerrIntegration } from "./jellyseerr/jellyseerr-integration";
export { LidarrIntegration } from "./media-organizer/lidarr/lidarr-integration";
export { RadarrIntegration } from "./media-organizer/radarr/radarr-integration";
export { ReadarrIntegration } from "./media-organizer/readarr/readarr-integration";
export { SonarrIntegration } from "./media-organizer/sonarr/sonarr-integration";
export { NextcloudIntegration } from "./nextcloud/nextcloud.integration";
export { GotifyIntegration } from "./gotify/gotify-integration";
export { NTFYIntegration } from "./ntfy/ntfy-integration";
export { OpenMediaVaultIntegration } from "./openmediavault/openmediavault-integration";
export { GlancesIntegration } from "./glances/glances-integration";
export { OverseerrIntegration } from "./overseerr/overseerr-integration";
export { SeerrIntegration } from "./seerr/seerr-integration";
export { PiHoleIntegrationV5 } from "./pi-hole/v5/pi-hole-integration-v5";
export { PiHoleIntegrationV6 } from "./pi-hole/v6/pi-hole-integration-v6";
export { PlexIntegration } from "./plex/plex-integration";
export { ProwlarrIntegration } from "./prowlarr/prowlarr-integration";
export { TrueNasIntegration } from "./truenas/truenas-integration";
export { SynologyIntegration } from "./synology/synology-integration";
export { UnraidIntegration } from "./unraid/unraid-integration";
export { OPNsenseIntegration } from "./opnsense/opnsense-integration";
export { ICalIntegration } from "./ical/ical-integration";
export { CoolifyIntegration } from "./coolify/coolify-integration";
export { ImmichIntegration } from "./immich/immich-integration";
export { TracearrIntegration } from "./tracearr/tracearr-integration";
export { SpeedtestTrackerIntegration } from "./speedtest-tracker/speedtest-tracker-integration";
export { AudiobookshelfIntegration } from "./audiobookshelf/audiobookshelf-integration";
export { NavidromeIntegration } from "./navidrome/navidrome-integration";
export { UptimeKumaIntegration } from "./uptime-kuma/uptime-kuma-integration";
export { UmamiIntegration } from "./umami/umami-integration";
export { PeaNutIntegration } from "./peanut/peanut-integration";
export { BazarrIntegration } from "./bazarr/bazarr-integration";
export { TraefikIntegration } from "./traefik/traefik-integration";
// Types
export type { IntegrationInput } from "./base/integration";
export type { PiHoleIntegrationV6 } from "./pi-hole/v6/pi-hole-integration-v6";
export type { DownloadClientJobsAndStatus } from "./interfaces/downloads/download-client-data";
export type { ExtendedDownloadClientItem } from "./interfaces/downloads/download-client-items";
export type { ExtendedClientStatus } from "./interfaces/downloads/download-client-status";
@@ -12,11 +59,8 @@ export type {
FirewallMemorySummary,
} from "./interfaces/firewall-summary/firewall-summary-types";
export type { SystemHealthMonitoring } from "./interfaces/health-monitoring/health-monitoring-types";
export type {
MediaRequestList,
MediaRequestStats,
UpstreamMediaRequestStatus,
} from "./interfaces/media-requests/media-request-types";
export { UpstreamMediaRequestStatus } from "./interfaces/media-requests/media-request-types";
export type { MediaRequestList, MediaRequestStats } from "./interfaces/media-requests/media-request-types";
export type { StreamSession } from "./interfaces/media-server/media-server-types";
export type { EntityState } from "./interfaces/smart-home/smart-home-types";
export type {
@@ -51,4 +95,11 @@ export type {
} from "./archive-team-warrior/archive-team-warrior-types";
export type { WudStats, WudContainerUpdate } from "./wud/wud-types";
// Schemas
export { anchorNotesListInputSchema, anchorNoteUpdateInputSchema } from "./anchor/anchor-types";
export { downloadClientItemSchema } from "./interfaces/downloads/download-client-items";
// Helpers
export { createIntegrationAsync } from "./base/creator";
export { simulateResponseContractAsync } from "./base/response-contract";
export type { ResponseContractFixture, ResponseContractParser } from "./base/response-contract";