import type { IChallengeAssessRequest, IChallengeDecision, IChallengeProvider, IChallengeProviderManifest, IChallengeRenderRequest, IChallengeRenderResponse, IChallengeType, IChallengeVerifyRequest, IChallengeVerifyResult, } from './interfaces.js'; export interface ISmartChallengeProviderOptions { providerId?: string; label?: string; description?: string; challengeTypes?: IChallengeType[]; } export class SmartChallengeProvider implements IChallengeProvider { public readonly providerId: string; private readonly label: string; private readonly description?: string; private challengeTypes = new Map(); constructor(optionsArg: ISmartChallengeProviderOptions = {}) { this.providerId = optionsArg.providerId || 'smartchallenge'; this.label = optionsArg.label || 'SmartChallenge'; this.description = optionsArg.description; for (const challengeType of optionsArg.challengeTypes || []) { this.registerChallengeType(challengeType); } } public registerChallengeType(challengeTypeArg: IChallengeType): void { if (!challengeTypeArg.challengeType) { throw new Error('Challenge type requires a challengeType identifier'); } this.challengeTypes.set(challengeTypeArg.challengeType, challengeTypeArg); } public getChallengeType(challengeTypeArg: string): IChallengeType | undefined { return this.challengeTypes.get(challengeTypeArg); } public async getManifest(): Promise { return { providerId: this.providerId, label: this.label, ...(this.description ? { description: this.description } : {}), challengeTypes: [...this.challengeTypes.values()].map((challengeType) => challengeType.getManifest()), }; } public async assess(requestArg: IChallengeAssessRequest): Promise { return this.getRequiredChallengeType(requestArg.challenge.challengeType).assess(requestArg); } public async render(requestArg: IChallengeRenderRequest): Promise { return this.getRequiredChallengeType(requestArg.challenge.challengeType).render(requestArg); } public async verify(requestArg: IChallengeVerifyRequest): Promise { return this.getRequiredChallengeType(requestArg.challenge.challengeType).verify(requestArg); } private getRequiredChallengeType(challengeTypeArg: string): IChallengeType { const challengeType = this.challengeTypes.get(challengeTypeArg); if (!challengeType) { throw new Error(`Challenge type '${challengeTypeArg}' is not registered for provider '${this.providerId}'`); } return challengeType; } }