Integracion con NestJS
Esta es la guia de integracion con NestJS, basada en la implementacion de WordyGo
(DisnomiaHttpAdapter).
Variables de entorno
ENGINE_TRANSPORT=httpENGINE_HTTP_URL=https://api.disnomia.econdor.comENGINE_API_KEY=pi_com_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxENGINE_TIMEOUT_MS=5000Modulo y servicio
import { Module } from '@nestjs/common';import { HttpModule } from '@nestjs/axios';import { ConfigModule } from '@nestjs/config';import { DisnomiaService } from './disnomia.service';
@Module({ imports: [ HttpModule.register({ timeout: parseInt(process.env.ENGINE_TIMEOUT_MS ?? '5000') }), ConfigModule, ], providers: [DisnomiaService], exports: [DisnomiaService],})export class DisnomiaModule {}import { Injectable, Logger } from '@nestjs/common';import { HttpService } from '@nestjs/axios';import { firstValueFrom } from 'rxjs';
export interface EvaluatePayload { exerciseId: string; area: string; type: string; answer: string; correctAnswer?: string | string[]; content?: Record<string, unknown>; difficulty?: number;}
export interface EvaluateResult { correct: boolean; score: number; feedback: string; metadata: { area: string; type: string };}
@Injectable()export class DisnomiaService { private readonly logger = new Logger(DisnomiaService.name); private readonly baseUrl = process.env.ENGINE_HTTP_URL!; private readonly apiKey = process.env.ENGINE_API_KEY!;
constructor(private readonly http: HttpService) {}
async evaluate(payload: EvaluatePayload): Promise<EvaluateResult> { const { data } = await firstValueFrom( this.http.post<EvaluateResult>( `${this.baseUrl}/api/v1/exercises/evaluate`, payload, { headers: { 'x-api-key': this.apiKey } }, ), ); return data; }}Uso en un controlador
@Post('submit')async submitAnswer(@Body() dto: SubmitAnswerDto, @Req() req: Request) { const result = await this.disnomiaService.evaluate({ exerciseId: dto.exerciseId, area: dto.area, type: dto.type, answer: dto.answer, correctAnswer: dto.correctAnswer, });
return result;}Manejo de errores y fallback
Si el motor no esta disponible, puedes implementar un evaluador local como fallback:
async evaluate(payload: EvaluatePayload): Promise<EvaluateResult> { try { return await this.callEngine(payload); } catch (err) { this.logger.warn(`Engine unavailable, using local fallback: ${err.message}`); return this.localFallback(payload); }}
private localFallback(payload: EvaluatePayload): EvaluateResult { const correct = payload.answer === payload.correctAnswer; return { correct, score: correct ? 10 : 0, feedback: correct ? 'Correct!' : 'Incorrect.', metadata: { area: payload.area, type: payload.type }, };}