diff --git a/packages/integrations/src/base/creator.ts b/packages/integrations/src/base/creator.ts index 82c722d50..bdeb532b4 100644 --- a/packages/integrations/src/base/creator.ts +++ b/packages/integrations/src/base/creator.ts @@ -55,84 +55,86 @@ import type { Integration, IntegrationInput } from "./integration"; export const createIntegrationAsync = async ( integration: IntegrationInput & { kind: TKind }, -) => { +): Promise => { if (!(integration.kind in integrationCreators)) { throw new Error( `Unknown integration kind ${integration.kind}. Did you forget to add it to the integration creator?`, ); } - const creator = integrationCreators[integration.kind]; - - // factories are an array, to differentiate in js between class constructors and functions - if (Array.isArray(creator)) { - return (await creator[0](integration)) as IntegrationInstanceOfKind; - } - - return new creator(integration) as IntegrationInstanceOfKind; + return (await integrationCreators[integration.kind].create(integration)) as IntegrationInstanceByKind[TKind]; }; -type IntegrationInstance = new (integration: IntegrationInput) => Integration; +type IntegrationConstructor = new ( + integration: IntegrationInput, +) => TIntegration; +type IntegrationFactory = ( + input: IntegrationInput, +) => Promise; +type IntegrationCreator = { + create: (input: IntegrationInput) => TIntegration | Promise; +}; + +const fromClass = (Constructor: IntegrationConstructor) => ({ + create: (input: IntegrationInput) => new Constructor(input), +}); + +const fromFactory = (create: IntegrationFactory) => ({ create }); -// factories are an array, to differentiate in js between class constructors and functions export const integrationCreators = { - anchor: AnchorIntegration, - piHole: [createPiHoleIntegrationAsync], - adGuardHome: AdGuardHomeIntegration, - technitiumDns: [createTechnitiumDnsIntegrationAsync], - homeAssistant: HomeAssistantIntegration, - jellyfin: JellyfinIntegration, - plex: PlexIntegration, - sonarr: SonarrIntegration, - radarr: RadarrIntegration, - sabNzbd: SabnzbdIntegration, - nzbGet: NzbGetIntegration, - qBittorrent: QBitTorrentIntegration, - deluge: DelugeIntegration, - transmission: TransmissionIntegration, - slskd: SlskdIntegration, - aria2: Aria2Integration, - jellyseerr: JellyseerrIntegration, - seerr: SeerrIntegration, - overseerr: OverseerrIntegration, - prowlarr: ProwlarrIntegration, - openmediavault: OpenMediaVaultIntegration, - lidarr: LidarrIntegration, - readarr: ReadarrIntegration, - dashDot: DashDotIntegration, - tdarr: TdarrIntegration, - proxmox: ProxmoxIntegration, - emby: EmbyIntegration, - nextcloud: NextcloudIntegration, - unifiController: UnifiControllerIntegration, - opnsense: OPNsenseIntegration, - ical: ICalIntegration, - ntfy: NTFYIntegration, - gotify: GotifyIntegration, - mock: MockIntegration, - truenas: TrueNasIntegration, - synology: SynologyIntegration, - unraid: UnraidIntegration, - coolify: CoolifyIntegration, - tracearr: TracearrIntegration, - glances: GlancesIntegration, - immich: ImmichIntegration, - paperlessNgx: PaperlessNgxIntegration, - speedtestTracker: SpeedtestTrackerIntegration, - audiobookshelf: AudiobookshelfIntegration, - navidrome: NavidromeIntegration, - umami: UmamiIntegration, - gluetun: GluetunIntegration, - archiveTeamWarrior: ArchiveTeamWarriorIntegration, - uptimeKuma: UptimeKumaIntegration, - peaNut: PeaNutIntegration, - beszel: BeszelIntegration, -} satisfies Record Promise]>; + anchor: fromClass(AnchorIntegration), + piHole: fromFactory(createPiHoleIntegrationAsync), + adGuardHome: fromClass(AdGuardHomeIntegration), + technitiumDns: fromFactory(createTechnitiumDnsIntegrationAsync), + homeAssistant: fromClass(HomeAssistantIntegration), + jellyfin: fromClass(JellyfinIntegration), + plex: fromClass(PlexIntegration), + sonarr: fromClass(SonarrIntegration), + radarr: fromClass(RadarrIntegration), + sabNzbd: fromClass(SabnzbdIntegration), + nzbGet: fromClass(NzbGetIntegration), + qBittorrent: fromClass(QBitTorrentIntegration), + deluge: fromClass(DelugeIntegration), + transmission: fromClass(TransmissionIntegration), + slskd: fromClass(SlskdIntegration), + aria2: fromClass(Aria2Integration), + jellyseerr: fromClass(JellyseerrIntegration), + seerr: fromClass(SeerrIntegration), + overseerr: fromClass(OverseerrIntegration), + prowlarr: fromClass(ProwlarrIntegration), + openmediavault: fromClass(OpenMediaVaultIntegration), + lidarr: fromClass(LidarrIntegration), + readarr: fromClass(ReadarrIntegration), + dashDot: fromClass(DashDotIntegration), + tdarr: fromClass(TdarrIntegration), + proxmox: fromClass(ProxmoxIntegration), + emby: fromClass(EmbyIntegration), + nextcloud: fromClass(NextcloudIntegration), + unifiController: fromClass(UnifiControllerIntegration), + opnsense: fromClass(OPNsenseIntegration), + ical: fromClass(ICalIntegration), + ntfy: fromClass(NTFYIntegration), + gotify: fromClass(GotifyIntegration), + mock: fromClass(MockIntegration), + truenas: fromClass(TrueNasIntegration), + synology: fromClass(SynologyIntegration), + unraid: fromClass(UnraidIntegration), + coolify: fromClass(CoolifyIntegration), + tracearr: fromClass(TracearrIntegration), + glances: fromClass(GlancesIntegration), + immich: fromClass(ImmichIntegration), + paperlessNgx: fromClass(PaperlessNgxIntegration), + speedtestTracker: fromClass(SpeedtestTrackerIntegration), + audiobookshelf: fromClass(AudiobookshelfIntegration), + navidrome: fromClass(NavidromeIntegration), + umami: fromClass(UmamiIntegration), + gluetun: fromClass(GluetunIntegration), + archiveTeamWarrior: fromClass(ArchiveTeamWarriorIntegration), + uptimeKuma: fromClass(UptimeKumaIntegration), + peaNut: fromClass(PeaNutIntegration), + beszel: fromClass(BeszelIntegration), +} satisfies Record; -type IntegrationInstanceOfKind = { - [kind in TKind]: (typeof integrationCreators)[kind] extends [(input: IntegrationInput) => Promise] - ? Awaited> - : (typeof integrationCreators)[kind] extends IntegrationInstance - ? InstanceType<(typeof integrationCreators)[kind]> - : never; -}[TKind]; +type IntegrationInstanceByKind = { + [TKind in keyof typeof integrationCreators]: Awaited>; +};