Skip to content

Integracion con NestJS

Esta es la guia de integracion con NestJS, basada en la implementacion de WordyGo (DisnomiaHttpAdapter).

Variables de entorno

ENGINE_TRANSPORT=http
ENGINE_HTTP_URL=https://api.disnomia.econdor.com
ENGINE_API_KEY=pi_com_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
ENGINE_TIMEOUT_MS=5000

Modulo y servicio

disnomia/disnomia.module.ts
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 {}
disnomia/disnomia.service.ts
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 },
};
}