Compare commits

...
2 Commits
2 changed files with 75 additions and 72 deletions

No files matched your search

@@ -196,6 +196,7 @@ export type HomarrDocumentationPath =
| "/docs/integrations/slskd" | "/docs/integrations/slskd"
| "/docs/integrations/sonarr" | "/docs/integrations/sonarr"
| "/docs/integrations/speedtest-tracker" | "/docs/integrations/speedtest-tracker"
| "/docs/integrations/synology"
| "/docs/integrations/tdarr" | "/docs/integrations/tdarr"
| "/docs/integrations/technitium-dns" | "/docs/integrations/technitium-dns"
| "/docs/integrations/tracearr" | "/docs/integrations/tracearr"
@@ -257,8 +258,8 @@ export type HomarrDocumentationPath =
| "/docs/widgets/smart-home-execute-automation" | "/docs/widgets/smart-home-execute-automation"
| "/docs/widgets/speedtest-tracker" | "/docs/widgets/speedtest-tracker"
| "/docs/widgets/stock-price" | "/docs/widgets/stock-price"
| "/docs/widgets/system-resources"
| "/docs/widgets/system-disks" | "/docs/widgets/system-disks"
| "/docs/widgets/system-resources"
| "/docs/widgets/timetable" | "/docs/widgets/timetable"
| "/docs/widgets/tracearr" | "/docs/widgets/tracearr"
| "/docs/widgets/umami" | "/docs/widgets/umami"
@@ -349,8 +350,8 @@ export type HomarrDocumentationPath =
| "/docs/widgets/firewall" | "/docs/widgets/firewall"
| "/docs/widgets/notifications" | "/docs/widgets/notifications"
| "/docs/widgets/system-resources" | "/docs/widgets/system-resources"
| "/docs/widgets/system-disks"
| "/docs/widgets/coolify" | "/docs/widgets/coolify"
| "/docs/widgets/system-disks"
| "/docs/widgets/timetable" | "/docs/widgets/timetable"
| "/docs/widgets/immich-server-stats" | "/docs/widgets/immich-server-stats"
| "/docs/widgets/immich-album-carousel" | "/docs/widgets/immich-album-carousel"
+72 -70
View File
@@ -55,84 +55,86 @@ import type { Integration, IntegrationInput } from "./integration";
export const createIntegrationAsync = async <TKind extends keyof typeof integrationCreators>( export const createIntegrationAsync = async <TKind extends keyof typeof integrationCreators>(
integration: IntegrationInput & { kind: TKind }, integration: IntegrationInput & { kind: TKind },
) => { ): Promise<IntegrationInstanceByKind[TKind]> => {
if (!(integration.kind in integrationCreators)) { if (!(integration.kind in integrationCreators)) {
throw new Error( throw new Error(
`Unknown integration kind ${integration.kind}. Did you forget to add it to the integration creator?`, `Unknown integration kind ${integration.kind}. Did you forget to add it to the integration creator?`,
); );
} }
const creator = integrationCreators[integration.kind]; return (await integrationCreators[integration.kind].create(integration)) as IntegrationInstanceByKind[TKind];
// factories are an array, to differentiate in js between class constructors and functions
if (Array.isArray(creator)) {
return (await creator[0](integration)) as IntegrationInstanceOfKind<TKind>;
}
return new creator(integration) as IntegrationInstanceOfKind<TKind>;
}; };
type IntegrationInstance = new (integration: IntegrationInput) => Integration; type IntegrationConstructor<TIntegration extends Integration = Integration> = new (
integration: IntegrationInput,
) => TIntegration;
type IntegrationFactory<TIntegration extends Integration = Integration> = (
input: IntegrationInput,
) => Promise<TIntegration>;
type IntegrationCreator<TIntegration extends Integration = Integration> = {
create: (input: IntegrationInput) => TIntegration | Promise<TIntegration>;
};
const fromClass = <TIntegration extends Integration>(Constructor: IntegrationConstructor<TIntegration>) => ({
create: (input: IntegrationInput) => new Constructor(input),
});
const fromFactory = <TIntegration extends Integration>(create: IntegrationFactory<TIntegration>) => ({ create });
// factories are an array, to differentiate in js between class constructors and functions
export const integrationCreators = { export const integrationCreators = {
anchor: AnchorIntegration, anchor: fromClass(AnchorIntegration),
piHole: [createPiHoleIntegrationAsync], piHole: fromFactory(createPiHoleIntegrationAsync),
adGuardHome: AdGuardHomeIntegration, adGuardHome: fromClass(AdGuardHomeIntegration),
technitiumDns: [createTechnitiumDnsIntegrationAsync], technitiumDns: fromFactory(createTechnitiumDnsIntegrationAsync),
homeAssistant: HomeAssistantIntegration, homeAssistant: fromClass(HomeAssistantIntegration),
jellyfin: JellyfinIntegration, jellyfin: fromClass(JellyfinIntegration),
plex: PlexIntegration, plex: fromClass(PlexIntegration),
sonarr: SonarrIntegration, sonarr: fromClass(SonarrIntegration),
radarr: RadarrIntegration, radarr: fromClass(RadarrIntegration),
sabNzbd: SabnzbdIntegration, sabNzbd: fromClass(SabnzbdIntegration),
nzbGet: NzbGetIntegration, nzbGet: fromClass(NzbGetIntegration),
qBittorrent: QBitTorrentIntegration, qBittorrent: fromClass(QBitTorrentIntegration),
deluge: DelugeIntegration, deluge: fromClass(DelugeIntegration),
transmission: TransmissionIntegration, transmission: fromClass(TransmissionIntegration),
slskd: SlskdIntegration, slskd: fromClass(SlskdIntegration),
aria2: Aria2Integration, aria2: fromClass(Aria2Integration),
jellyseerr: JellyseerrIntegration, jellyseerr: fromClass(JellyseerrIntegration),
seerr: SeerrIntegration, seerr: fromClass(SeerrIntegration),
overseerr: OverseerrIntegration, overseerr: fromClass(OverseerrIntegration),
prowlarr: ProwlarrIntegration, prowlarr: fromClass(ProwlarrIntegration),
openmediavault: OpenMediaVaultIntegration, openmediavault: fromClass(OpenMediaVaultIntegration),
lidarr: LidarrIntegration, lidarr: fromClass(LidarrIntegration),
readarr: ReadarrIntegration, readarr: fromClass(ReadarrIntegration),
dashDot: DashDotIntegration, dashDot: fromClass(DashDotIntegration),
tdarr: TdarrIntegration, tdarr: fromClass(TdarrIntegration),
proxmox: ProxmoxIntegration, proxmox: fromClass(ProxmoxIntegration),
emby: EmbyIntegration, emby: fromClass(EmbyIntegration),
nextcloud: NextcloudIntegration, nextcloud: fromClass(NextcloudIntegration),
unifiController: UnifiControllerIntegration, unifiController: fromClass(UnifiControllerIntegration),
opnsense: OPNsenseIntegration, opnsense: fromClass(OPNsenseIntegration),
ical: ICalIntegration, ical: fromClass(ICalIntegration),
ntfy: NTFYIntegration, ntfy: fromClass(NTFYIntegration),
gotify: GotifyIntegration, gotify: fromClass(GotifyIntegration),
mock: MockIntegration, mock: fromClass(MockIntegration),
truenas: TrueNasIntegration, truenas: fromClass(TrueNasIntegration),
synology: SynologyIntegration, synology: fromClass(SynologyIntegration),
unraid: UnraidIntegration, unraid: fromClass(UnraidIntegration),
coolify: CoolifyIntegration, coolify: fromClass(CoolifyIntegration),
tracearr: TracearrIntegration, tracearr: fromClass(TracearrIntegration),
glances: GlancesIntegration, glances: fromClass(GlancesIntegration),
immich: ImmichIntegration, immich: fromClass(ImmichIntegration),
paperlessNgx: PaperlessNgxIntegration, paperlessNgx: fromClass(PaperlessNgxIntegration),
speedtestTracker: SpeedtestTrackerIntegration, speedtestTracker: fromClass(SpeedtestTrackerIntegration),
audiobookshelf: AudiobookshelfIntegration, audiobookshelf: fromClass(AudiobookshelfIntegration),
navidrome: NavidromeIntegration, navidrome: fromClass(NavidromeIntegration),
umami: UmamiIntegration, umami: fromClass(UmamiIntegration),
gluetun: GluetunIntegration, gluetun: fromClass(GluetunIntegration),
archiveTeamWarrior: ArchiveTeamWarriorIntegration, archiveTeamWarrior: fromClass(ArchiveTeamWarriorIntegration),
uptimeKuma: UptimeKumaIntegration, uptimeKuma: fromClass(UptimeKumaIntegration),
peaNut: PeaNutIntegration, peaNut: fromClass(PeaNutIntegration),
beszel: BeszelIntegration, beszel: fromClass(BeszelIntegration),
} satisfies Record<IntegrationKind, IntegrationInstance | [(input: IntegrationInput) => Promise<Integration>]>; } satisfies Record<IntegrationKind, IntegrationCreator>;
type IntegrationInstanceOfKind<TKind extends keyof typeof integrationCreators> = { type IntegrationInstanceByKind = {
[kind in TKind]: (typeof integrationCreators)[kind] extends [(input: IntegrationInput) => Promise<Integration>] [TKind in keyof typeof integrationCreators]: Awaited<ReturnType<(typeof integrationCreators)[TKind]["create"]>>;
? Awaited<ReturnType<(typeof integrationCreators)[kind][0]>> };
: (typeof integrationCreators)[kind] extends IntegrationInstance
? InstanceType<(typeof integrationCreators)[kind]>
: never;
}[TKind];