From a1538504cf8dff08841fae3b7ab6c23b872adb2e Mon Sep 17 00:00:00 2001 From: Leo Developer Date: Sat, 26 Aug 2023 12:17:24 +0200 Subject: [PATCH] make it better see the linked issue/pr for more information on motivation --- src/api.ts | 63 +++++++++++++++++++++++++++++++++++++ src/detector.ts | 84 +++---------------------------------------------- src/index.ts | 5 +++ 3 files changed, 72 insertions(+), 80 deletions(-) create mode 100644 src/api.ts diff --git a/src/api.ts b/src/api.ts new file mode 100644 index 00000000..fe11d87f --- /dev/null +++ b/src/api.ts @@ -0,0 +1,63 @@ +import { detectors } from './detectors' +import { sources } from './sources' +import { BotdError, BotDetectionResult, BotKind, Component, ComponentDict, DetectionDict, State } from './types' + +export function detect(components: ComponentDict): [DetectionDict, BotDetectionResult] { + const detections = {} as DetectionDict + let finalDetection: BotDetectionResult = { + bot: false, + } + + for (const detectorName in detectors) { + const detector = detectors[detectorName as keyof typeof detectors] + const detectorRes = detector(components) + + let detection: BotDetectionResult = { bot: false } + + if (typeof detectorRes === 'string') { + detection = { bot: true, botKind: detectorRes } + } else if (detectorRes) { + detection = { bot: true, botKind: BotKind.Unknown } + } + + detections[detectorName as keyof typeof detectors] = detection + + if (detection.bot) { + finalDetection = detection + } + } + + return [detections, finalDetection] +} + +export async function collect(): Promise { + const components = {} as ComponentDict + const sourcesKeys = Object.keys(sources) as (keyof typeof sources)[] + + await Promise.all( + sourcesKeys.map(async (sourceKey) => { + const res = sources[sourceKey] + + try { + components[sourceKey] = ({ + value: await res(), + state: State.Success, + } as Component) as any + } catch (error) { + if (error instanceof BotdError) { + components[sourceKey] = { + state: error.state, + error: `${error.name}: ${error.message}`, + } + } else { + components[sourceKey] = { + state: State.UnexpectedBehaviour, + error: error instanceof Error ? `${error.name}: ${error.message}` : String(error), + } + } + } + }), + ) + + return components +} diff --git a/src/detector.ts b/src/detector.ts index 6d5b476e..a63f45fc 100644 --- a/src/detector.ts +++ b/src/detector.ts @@ -1,15 +1,5 @@ -import { detectors } from './detectors' -import { sources } from './sources' -import { - BotdError, - BotDetectionResult, - BotDetectorInterface, - BotKind, - Component, - ComponentDict, - DetectionDict, - State, -} from './types' +import { BotDetectionResult, BotDetectorInterface, ComponentDict, DetectionDict } from './types' +import { collect, detect } from './api' /** * Class representing a bot detector. @@ -30,16 +20,6 @@ export default class BotDetector implements BotDetectorInterface { return this.detections } - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - protected getSources() { - return sources - } - - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - protected getDetectors() { - return detectors - } - /** * @inheritdoc */ @@ -48,35 +28,9 @@ export default class BotDetector implements BotDetectorInterface { throw new Error("BotDetector.detect can't be called before BotDetector.collect") } - const components = this.components - const detectors = this.getDetectors() - - const detections = {} as DetectionDict - let finalDetection: BotDetectionResult = { - bot: false, - } - - for (const detectorName in detectors) { - const detector = detectors[detectorName as keyof typeof detectors] - const detectorRes = detector(components) - - let detection: BotDetectionResult = { bot: false } - - if (typeof detectorRes === 'string') { - detection = { bot: true, botKind: detectorRes } - } else if (detectorRes) { - detection = { bot: true, botKind: BotKind.Unknown } - } - - detections[detectorName as keyof typeof detectors] = detection - - if (detection.bot) { - finalDetection = detection - } - } + const [detections, finalDetection] = detect(this.components) this.detections = detections - return finalDetection } @@ -84,37 +38,7 @@ export default class BotDetector implements BotDetectorInterface { * @inheritdoc */ public async collect(): Promise { - const sources = this.getSources() - const components = {} as ComponentDict - - const sourcesKeys = Object.keys(sources) as (keyof typeof sources)[] - - await Promise.all( - sourcesKeys.map(async (sourceKey) => { - const res = sources[sourceKey] - - try { - components[sourceKey] = ({ - value: await res(), - state: State.Success, - } as Component) as any - } catch (error) { - if (error instanceof BotdError) { - components[sourceKey] = { - state: error.state, - error: `${error.name}: ${error.message}`, - } - } else { - components[sourceKey] = { - state: State.UnexpectedBehaviour, - error: error instanceof Error ? `${error.name}: ${error.message}` : String(error), - } - } - } - }), - ) - - this.components = components + this.components = await collect() return this.components } } diff --git a/src/index.ts b/src/index.ts index e3b9bbcf..6b08715b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,9 @@ import { version } from '../package.json' import BotDetector from './detector' import { sources, WindowSizePayload, ProcessPayload, DistinctivePropertiesPayload } from './sources' +import { detectors } from './detectors' import { BotdError, BotDetectorInterface, BotKind, BotDetectionResult } from './types' +import { collect, detect } from './api' /** * Options for BotD loading @@ -48,6 +50,9 @@ export default { load } /** Not documented, out of Semantic Versioning, usage is at your own risk */ export { sources, + detectors, + collect, + detect, BotdError, WindowSizePayload, ProcessPayload,