Controladores y rutas

This commit is contained in:
2026-04-17 15:49:53 +02:00
parent da2413002b
commit 32990b4dcd
7 changed files with 130 additions and 25 deletions

View File

@@ -1,34 +1,110 @@
import { ConsumeMessage } from "amqplib";
import { SimNosUsecases } from "./SimNOS.usecases";
import { EventBus } from "sim-shared/domain/EventBus.port.js";
import { Result } from "sim-shared/domain/Result.js";
import { SimEvents } from "sim-shared/domain/SimEvents.js";
import { error } from "node:console";
export class SimNosController {
constructor(
uscases: SimNosUsecases
private uscases: SimNosUsecases,
private eventBus: EventBus,
) {
}
private validateMsg(msg: ConsumeMessage | null) {
if (msg == undefined) return false;
const msgData = this.decodeMsg(msg) as SimEvents.general
if (msgData == undefined || msgData.payload == undefined) throw new Error("Mensaje invalido")
return msgData;
}
private decodeMsg(msg: ConsumeMessage): object | undefined {
if (msg.content == undefined) {
console.warn('[Sim.controller] Mensaje vacío');
return undefined;
}
try {
// Convertir el Buffer a String (UTF-8)
const contentJson = JSON.parse(Buffer.from(msg.content).toString('utf8'))
return contentJson;
} catch (error) {
console.error('Error al decodificar JSON:', error);
console.error(Buffer.from(msg.content).toString(("utf8")))
// Aquí podrías decidir devolver el string crudo o null
return undefined;
}
}
/**
* Metodo duplicado se puede generalizar la a una clase sharedController con las funciones basicas
*/
private async tryUseCase<T extends any>
(msg: ConsumeMessage, usecase: () => Promise<Result<string, T>>): Promise<Result<string, T>> {
try {
const result = await usecase()
if (result.error == undefined) {
await this.eventBus.ack(msg)
return result
} else {
console.error("Error general procesando el caso de uso", result.error)
this.eventBus.nack(msg)
return result
}
} catch (e) {
console.error("Error general procesando el caso de uso")
this.eventBus.nack(msg)
return {
error: String(e)
}
}
}
public activate() {
return async (msg: ConsumeMessage) => {
console.log("Evento activate ", msg)
console.log("[i] Evento activate ", msg)
const data = this.validateMsg(msg) as SimEvents.activation
const iccid = data.payload.iccid
const res = await this.tryUseCase(msg, this.uscases.activate({
iccid: iccid
}))
return res;
}
}
public suspend() {
return async (msg: ConsumeMessage) => {
console.log("Evento suspend ", msg)
const data = this.validateMsg(msg) as SimEvents.suspend
const iccid = data.payload.iccid
const res = await this.tryUseCase(msg, this.uscases.suspend({
iccid: iccid
}))
return res;
}
}
public terminate() {
return async (msg: ConsumeMessage) => {
console.log("Evento termiante ", msg)
console.log("Evento termiante no soportado ", msg)
}
}
public preActivate() {
public reActivate() {
return async (msg: ConsumeMessage) => {
console.log("Evento preActivate ", msg)
console.log("Evento reActivate ", msg)
const data = this.validateMsg(msg) as SimEvents.reActivation
const iccid = data.payload.iccid
const res = await this.tryUseCase(msg, this.uscases.reactivate({
iccid: iccid
}))
return res;
}
}
}

View File

@@ -7,21 +7,24 @@
import { ConsumeMessage } from "amqplib";
import { SimNosController } from "./SimNOS.controller.js";
import { EventBus } from "sim-shared/domain/EventBus.port.js";
import { Result } from "sim-shared/domain/Result.js";
type FuncType = ((m: ConsumeMessage) => Promise<Result<string, any>>)
export class SimNosRouter {
private readonly routes: Map<string, undefined | ((m: ConsumeMessage) => Promise<any>)>;
private readonly routes: Map<string, FuncType>;
constructor(
private readonly simController: SimNosController,
private readonly eventBus: EventBus
) {
this.routes = new Map([
["select", undefined],
this.routes = new Map<string, FuncType>([
//["select", undefined],
["activate", this.simController.activate()],
["pause", this.simController.suspend()],
["cancel", this.simController.terminate()],
//["reactivate", this.simController.reActivate()],
["preActivate", this.simController.preActivate()]
["reactivate", this.simController.reActivate()],
//["cancel", this.simController.terminate()],
//["preActivate", this.simController.preActivate()]
]);
}
@@ -57,10 +60,10 @@ export class SimNosRouter {
console.log("[Router] Ejecutando operación:", action);
// El controlador devuelve una función (thunk) que debe ser ejecutada
const executeParams = await handler(msg);
const executeParams = handler(msg);
if (typeof executeParams === "function") {
await executeParams();
const res = await executeParams;
}
} catch (error) {

View File

@@ -7,7 +7,7 @@
*
*/
import { NosHttpClient } from "infrastructure/NosHttpClient";
import { NosRepository } from "infrastructure/NOSRepository";
import { NosRepository } from "infrastructure/NosRepository";
export class SimNosUsecases {
constructor(
@@ -16,18 +16,44 @@ export class SimNosUsecases {
) {
}
public activate() {
return (args: { iccid: string }) => {
public activate(args: { iccid: string }) {
return async () => {
try {
return await this.nosRepository.activateSim(args.iccid)
} catch (e) {
return {
error: "Error general de activación de sim" + String(e)
}
}
}
}
public suspend() {
public suspend(args: { iccid: string }) {
return async () => {
try {
return await this.nosRepository.bar(args.iccid)
} catch (e) {
return {
error: "Error general de suspension de sim" + String(e)
}
}
}
}
public terminate() {
public reactivate(args: { iccid: string }) {
return async () => {
try {
return await this.nosRepository.unbar(args.iccid)
} catch (e) {
return {
error: "Error general de reactivación de sim" + String(e)
}
}
}
}
public terminate(args: { iccid: string }) {
throw new Error("No hay termination para NOS")
}
}

View File

@@ -21,7 +21,6 @@ export class SimController {
) {
this.eventBus = eventBus
this.useCases = useCases
}
private decodeMsg(msg: ConsumeMessage): object | undefined {
@@ -109,7 +108,7 @@ export class SimController {
return async (msg: ConsumeMessage) => {
let msgData;
try {
msgData = this.validateMsg(msg) as SimEvents.pause
msgData = this.validateMsg(msg) as SimEvents.suspend
} catch (e) {
throw new Error("Error de preactivacion consumiendo el mensaje no es valido" + String(e))
}
@@ -136,7 +135,7 @@ export class SimController {
return async (msg: ConsumeMessage) => {
let msgData;
try {
msgData = this.validateMsg(msg) as SimEvents.pause
msgData = this.validateMsg(msg) as SimEvents.suspend
} catch (e) {
throw new Error("Error de reactivacion consumiendo el mensaje no es valido" + String(e))
}
@@ -165,7 +164,7 @@ export class SimController {
return async (msg: ConsumeMessage) => {
let msgData;
try {
msgData = this.validateMsg(msg) as SimEvents.pause
msgData = this.validateMsg(msg) as SimEvents.suspend
} catch (e) {
throw new Error("Error de suspension consumiendo el mensaje no es valido" + String(e))
}
@@ -195,7 +194,7 @@ export class SimController {
return async (msg: ConsumeMessage) => {
let msgData;
try {
msgData = this.validateMsg(msg) as SimEvents.pause
msgData = this.validateMsg(msg) as SimEvents.suspend
} catch (e) {
throw new Error("Error consumiendo el mensaje no es valido" + String(e))
}

View File

@@ -47,6 +47,7 @@ export namespace SimEvents {
options: {
}
}
export type suspend = pause
export type free = DomainEvent & {
key: `sim.${string}.free`,