@qq-framework/ddd
TypeScript icon, indicating that this package has built-in type declarations

3.6.1 • Public • Published

ddd

Como disparar eventos com nestjs

  • Dependencias
    • "@qq-framework/ddd": "^3.4.x"
    • "@qq-framework/basic": "^3.2.x"
  • Crie um provider em seu módulo utilizando a classe DomainEventPublisherNestImplService do @qq-framework/ddd
// any.module.ts

import { EventPublisher } from '@nestjs/cqrs'
import { DomainEventPublisherNestImplService } from '@qq-framework/ddd'

@Module({
    controllers: [
    ...
    ],
    providers: [
        ...
        {
            provide: 'NestDomainEventPublisher',
            useFactory(eventPublisher: EventPublisher) {
                return new DomainEventPublisherNestImplService(eventPublisher)
            },
            inject: [EventPublisher],
        }
        ...
    ],
    imports: [
        ...
    ],
})
export class CoreModule implements NestModule {}
  • Injete o provider criado no construtor da classe de serviço onde deseja disparar o evento, utilizando a interface DomainEventPublisherService do @qq-framework/basic
//any.service

import {
    AggregateRoot,
    DomainEventPublisherService,
} from '@qq-framework/basic'

...

constructor(
        @Inject('NestDomainEventPublisher') private readonly publisher: DomainEventPublisherService<AggregateRoot>
    ) {
    }

...
  • Para publicar o evento, utilize o publisher injetado na sua classe, passando o seu agregado.
...

const publish = await this.publisher.publish(campoExistente.value)
if (publish.isFailure()) return R.failure(publish.error)

...

Pooling de rotas

  • "@qq-framework/ddd": "^3.5.x"

Como adicionar um parâmetro de pooling de rotas.

Será via o decorator @Pooling. Este decorator irá receber a rota ser chamada para ter o retorno do processo sendo executado. Ele irá injetar um parâmetro string no exemplo chamado idPooling) no paramêtro do método. Ele será a chave de referência para a rota de busca.

Essa rota por sua vez no buildResponse irá devolver dentro do objeto uma chave poolingRoute. poolingRoute será a rota a ser requisitada para ter o retorno.

Exemplo:

@Controller("core")
export class CoreController extends AbstractController {
    private readonly logger = new Logger(CoreController.name);

    constructor(
        private readonly useCase: UseCase,
        private readonly query: Query
    ) {
        super(CoreController.name, CoreModule.name, {
            httpCodeMap,
            defaultHttpCodeErrors: 500,
        });
    }

    @Post("postar-mensagem")
    @Pooling("core/rota-pooling")
    public async executarMetodo(@Body() params: any, idPooling: string) {
        this.useCase.execute({ params, idPooling });

        return super.buildResponse({ result: Result.ok() });
    }

    @Get("rota-pooling/:id")
    public async executarMetodo(@Params() id: string) {
        const result = await this.query.execute(id);

        return super.buildResponse({ result });
    }
}

Migrando para versão 2.x.x

Se você estiver realizando uma migração da versão 1.x.x para versão 2.x.x os seguintes scripts devem ser executados no banco de dados da sua aplicação:

alter table public.process_log add column error_class varchar null;
alter table public.process_log add column error_type varchar null;

alter table public.single_thread_command_log add column error_class varchar null;
alter table public.single_thread_command_log add column error_type varchar null;

alter table public.event_log add column error_class varchar null;
alter table public.event_log add column error_type varchar null;

O impacto que essa versão deve gerar nas aplicações que estavam utilizando a versão 1.x.x será nos métodos de gravação de logs de erros. Os métodos de gravação de log como, por exemplo, ProcessLog.saveError, o parâmetro error, qua anteriormente recebia uma string, passou a receber uma instance de Error.

Implementando response padrão nos controllers

Para utilizar essa funcionalidade é necessário versão 2.1.0 do qq-framework/http ou superior.

Essa implementação visa padronizar os responses dos controllers das aplicações.

Em caso de sucesso, retornando HttpResponseOk e em caso de falha, HttpResponseError

export interface HttpResponseOk {
    data: any;
}

export interface HttpResponseError {
    erro: string;
    message: string;
}
//any.controller.ts

import { Body, Controller, Logger, Post } from '@nestjs/common'
import { AbstractController } from '@qq-framework/ddd'
import { PostarMensagemUseCase } from './application/usecases/PostarMensagem.usecase'
import { CoreModule } from './core.module'


const httpCodeMap: HttpCodeMap = {
    RepositoryException: 400,
}

@Controller('core')
export class CoreController extends AbstractController {
    private readonly logger = new Logger(CoreController.name)

    constructor(private readonly postarMensagemUseCase: PostarMensagemUseCase) {
        super(CoreController.name, CoreModule.name, {
            httpCodeMap,
            defaultHttpCodeErrors: 500,
        })
    }

    @Post('postar-mensagem')
    public async postarMensagem(@Body() params: any) {
        const result = await this.postarMensagemUseCase.execute({
            mensagem: {
                chave: params['chave'],
                conteudo: params['conteudo'],
                headers: params['headers'],
                topico: params['topico'],
            },
        })

        return super.buildResponse({
            data: result,
        })
    }
}

No código visto acima, primeiramente você deve definir quais o códigos HTTP que devem ser retornados para cada exceções possíveis que seu controller retornar para o client, conforme abaixo:

const httpCodeMap: HttpCodeMap = {
    RepositoryException: 400,
};

No construtor do seu controller você deve informar ao AbstractController as configurações dos seus responses HTTP, através da interface HttpResponseConfig

constructor() {
        const httpResponseConfig: HttpResponseConfig = {
            httpCodeMap,
            defaultHttpCodeErrors: 500,
        }
        super(VendaController.name, VendaModule.name, httpResponseConfig)
    }

A propriedade defaultHttpCodeError não é obrigatória, mas serve para indicar qual o http code que o seu controller retornará, caso a exceção não tenha sido mapeada pelo HttpCodeMap. Por default, este valor será 500

Para finalizar, você deve retornar o resultado do seu controller através do método buildResponse. O método buidResponse pode receber, além do parâmetro result, também headers e um parâmetro chamado successStatusCode que será utilizado como código http retornado pelo seu endpoint em caso de sucesso. Ambos os parâmetros são opcionais. Em caso de não informado o successStatusCode, será retornado 200.

    @Post('postar-mensagem')
    public async postarMensagem(@Body() params: any) {
        const result = await this.postarMensagemUseCase.execute({
            mensagem: {
                chave: params['chave'],
                conteudo: params['conteudo'],
                headers: params['headers'],
                topico: params['topico'],
            },
        })

        return super.buildResponse({
            result,
        })
    }

Em caso de sucesso o seu response será retornado para o client com o http code informado em successStatusCode ou 200 (default) e em caso de exceção, ele retornará o httpcode configurado no HttpCodeMap que foi passado no construtor.

Para finalizar, você deve adicionar ao seu projeto o HttpInterceptor disponibilizado no qq-framework/http

Readme

Keywords

none

Package Sidebar

Install

npm i @qq-framework/ddd

Weekly Downloads

88

Version

3.6.1

License

ISC

Unpacked Size

621 kB

Total Files

358

Last publish

Collaborators

  • carlos.castro.qq
  • guilhermegotin
  • fn_qq
  • juniordeitch
  • 6porto
  • lealhugui