diff --git a/src/booru/booru.service.spec.ts b/src/booru/booru.service.spec.ts index a12f69c..e4a6267 100644 --- a/src/booru/booru.service.spec.ts +++ b/src/booru/booru.service.spec.ts @@ -1,9 +1,10 @@ import { Test, TestingModule } from '@nestjs/testing' import { ConfigService } from '@nestjs/config' import { BooruTypesStringEnum } from '@alejandroakbal/universal-booru-wrapper' +import * as UBW from '@alejandroakbal/universal-booru-wrapper' import { BooruService } from './booru.service' import { booruQueriesDTO } from './dto/booru-queries.dto' -import { BooruEndpointParamsDTO } from './dto/request-booru.dto' +import { BooruEndpointParamsDTO, SupportedBooruType } from './dto/request-booru.dto' import { BooruAuthManagerService } from './services/booru-auth-manager.service' describe('BooruService', () => { @@ -123,4 +124,44 @@ describe('BooruService', () => { }) + + describe('Booru type resolution', () => { + const queries = { + baseEndpoint: 'kemono.cr' + } as booruQueriesDTO + + afterEach(() => { + if ((UBW as any).Kemono !== originalKemonoClass) { + ;(UBW as any).Kemono = originalKemonoClass + } + }) + + const originalKemonoClass = (UBW as any).Kemono + + it('should resolve kemono when the wrapper exports it', () => { + if (!originalKemonoClass) { + return + } + + const params: BooruEndpointParamsDTO = { + booruType: 'kemono' as SupportedBooruType + } + + const api = service.buildApiClass(params, queries) + + expect(api).toBeInstanceOf(originalKemonoClass) + }) + + it('should fail clearly when the wrapper does not export kemono', () => { + ;(UBW as any).Kemono = undefined + + const params: BooruEndpointParamsDTO = { + booruType: 'kemono' as SupportedBooruType + } + + expect(() => service.buildApiClass(params, queries)).toThrow( + 'Kemono booru type requires @alejandroakbal/universal-booru-wrapper version that exports Kemono' + ) + }) + }) }) diff --git a/src/booru/booru.service.ts b/src/booru/booru.service.ts index 5aa1f73..438ddd9 100644 --- a/src/booru/booru.service.ts +++ b/src/booru/booru.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@nestjs/common' +import { BadRequestException, Injectable, ServiceUnavailableException } from '@nestjs/common' import { ConfigService } from '@nestjs/config' import { BooruTypes, @@ -16,8 +16,9 @@ import { Rule34PahealNet, Rule34Xxx } from '@alejandroakbal/universal-booru-wrapper' +import * as UBW from '@alejandroakbal/universal-booru-wrapper' import { booruQueriesDTO } from './dto/booru-queries.dto' -import { BooruEndpointParamsDTO } from './dto/request-booru.dto' +import { BooruEndpointParamsDTO, SupportedBooruType } from './dto/request-booru.dto' import { BooruAuthManagerService } from './services/booru-auth-manager.service' @Injectable() @@ -112,7 +113,7 @@ export class BooruService { return {} } - private getApiClassByType(booruType: BooruTypesStringEnum) { + private getApiClassByType(booruType: SupportedBooruType) { switch (booruType) { case BooruTypesStringEnum.DANBOORU: return Danbooru @@ -140,6 +141,21 @@ export class BooruService { case BooruTypesStringEnum.REALBOORU_COM: return RealBooruCom + + case 'kemono': { + const maybeKemonoClass = (UBW as any).Kemono + + if (!maybeKemonoClass) { + throw new ServiceUnavailableException( + 'Kemono booru type requires @alejandroakbal/universal-booru-wrapper version that exports Kemono' + ) + } + + return maybeKemonoClass + } + + default: + throw new BadRequestException(`Unsupported booru type: ${booruType}`) } } } diff --git a/src/booru/dto/request-booru.dto.ts b/src/booru/dto/request-booru.dto.ts index a8dfa99..1dc89d6 100644 --- a/src/booru/dto/request-booru.dto.ts +++ b/src/booru/dto/request-booru.dto.ts @@ -1,12 +1,16 @@ import { BooruTypesStringEnum } from '@alejandroakbal/universal-booru-wrapper' import { IsDefined, IsIn, IsNotEmpty, IsString } from 'class-validator' -const BooruTypesToArray = Object.values(BooruTypesStringEnum) +const AdditionalBooruTypes = ['kemono'] as const + +export type SupportedBooruType = BooruTypesStringEnum | (typeof AdditionalBooruTypes)[number] + +const BooruTypesToArray = [...Object.values(BooruTypesStringEnum), ...AdditionalBooruTypes] export class BooruEndpointParamsDTO { @IsDefined() @IsNotEmpty() @IsString() @IsIn(BooruTypesToArray) - readonly booruType: BooruTypesStringEnum + readonly booruType: SupportedBooruType }