@gebittencourt/sdk-jsddd

Conjunto de utilitários para aplicações javascript com abordagens de Domain-Driven Design.

Usage no npm install needed!

<script type="module">
  import gebittencourtSdkJsddd from 'https://cdn.skypack.dev/@gebittencourt/sdk-jsddd';
</script>

README

Software Development Kit - Javascript DDD

Conjunto de utilitários para aplicações javascript com abordagens de Domain-Driven Design.

Abstrações de domínio

Objetos de valor, entidades, agregados, eventos de domínio, indicam o valor das classes no domínio e cada uma possui um objetivo específico. Sendo assim, algumas abstrações estão disponíveis neste SDK, afim de facilitar o entendimento e implementação das classes no domínio.

Objeto de valor

Classe abstrata apenas informativa: ValueObject.

Entidade

Classe abstrata que contém uma propriedade de identificação (id) com um tipo que deve ser indicado e com o validador NotNull (não permitindo informação nula ou indefinida): Entity.

Evento de domínio

Classe abstrata que contém uma propriedade abstrata forçando a indicação da versão do evento (eventVersion) e uma propriedade que indica a data em que o evento ocorreu (occurredOn) sendo automaticamente definida como a data atual no construtor.

Agregado

Classe abstrata apenas informativa que extende de uma entidade: Aggregate.

Repositório

Classe abstrata apenas informativa: DomainRepository.

Validações

A principal razão para usar a validação no modelo é para verificar a exatidão de qualquer um atributo/propriedade, qualquer objeto inteiro ou qualquer composição de objetos. Implementando Domain-Driven Design.

Validando atributos ou propriedades com decoradores

Para facilitar a implementação de validadores de atributos ou propriedades, é disponibilizado neste SDK, um conjunto de decoradores que definem restrições para estes.

O Decorator é um padrão estrutural que permite adicionar novos comportamentos aos objetos dinamicamente, colocando-os dentro de objetos wrapper especiais. Decorator em TypeScript; Veja também: Typescript Lang | Decorate your code with TypeScript decorators.

Ao decorar um atributo ou propriedade com um ou mais decoradores de restrições, você apenas define quais validações deverão ser aplicadas, porém, apenas será realizada a validação quando for invocado o método validate do utilitário ConstraintValidation para o objeto, ficando a critério do desenvolvedor realizar a validação no construtor, fábrica ou método específico. Também fica a critério do desenvolvedor o tratamento das validações, lançando um erro ou não, por exemplo, com o resultado do método validate.

Decorator Validação
@Valid Marca uma propriedade do tipo objeto para que também possua suas propriedades validadas em cascata.
@NotNull Propriedade não deve ser nulo ou indefinido.
@NotBlank Propriedade não deve ser nulo ou indefinido e deve conter, pelo menos, um caractere diferente de espaço em branco.
@Size O tamanho da propriedade deve respeitar as condições passadas para o decorador.

Exemplo

class Address {
  @NotBlank()
  id: string;

  @NotNull({
    message: 'Situation must not be null.',
  })
  situation: Situation;

  @Valid()
  zipCode: ZipCode;

  constructor(id: string, situation: Situation, zipCode: ZipCode) {
    this.id = id;
    this.situation = situation;
    this.zipCode = zipCode;
    const invalidConstraints = ConstraintValidation.validate(this);
    // Você pode avaliar o resultado de `invalidConstraints` para lançar ou não uma exceção ou realizar outro tratamento...
  }
}

Abstrações de consulta

Algumas abstrações estão disponíveis neste SDK, afim de facilitar o entendimento e implementação das classes de consulta.

Repositório

Classe abstrata apenas informativa: QueryRepository.

Tipos para consulta

A consulta de dados também necessita de alguns padrões e em relação a tipagem de dados de requisições e respostas, alguns Types estão disponíveis neste pacote:

Parâmetros de paginação

PaginationParam é o tipo que define os parâmetros de uma requisição em relação a paginação de dados, com as propriedades:

  • page: número da página desejada;
  • pageSize: quantidade de registros desejados;

Resposta de consulta de registros

GetAllResponse<DTO> é o tipo que define a resposta de uma requisição com o objetivo de retornar um ou mais registros. Possui as seguintes propriedades:

  • items: lista de registros representados pelo tipo DTO indicado;
  • hasNext: indicativo se existe ou não uma próxima página;
  • page: número da página requisitada;
  • pageSize: quantidade de registros requisitados;
  • length: total de registros existentes;

Filtro (Campo/Valor)

FieldValue<ValueType> é o tipo que define um filtro para ser aplicado em uma consulta. Possui as seguintes propriedades:

  • field: campo relacionado ao filtro;
  • value: valor para o filtro;

Utilitários

Para facilitar o desenvolvimento provendo uma sintaxe mais eficiente, são disponibilizados alguns facilitadores:

Construtor de filtros

FilterBuilder é um utilitário para definição de filtros com uma sintaxe fluída, conforme o exemplo:

const filters = FilterBuilder.where<string>({
  field: 'fieldA',
  value: 'valueA',
})
  .or<number>({
    field: 'fieldB',
    value: 10,
  })
  .and<Date>({
    field: 'fieldC',
    value: new Date(),
  })
  .and<string>({
    field: 'fieldD',
    value: 'valueD',
  })
  .or<string>({
    field: 'fieldE',
    value: 'valueE',
  })
  .build();

// Filters possuirá uma lista de `FieldValue`
// Para os operadores AND e OR, o field será igual a {{OPERATOR}} e
// o value será respectivamente AND ou OR

// [{ field: 'fieldA'      , value: 'valueA'   }]
// [{ field: '{{OPERATOR}}', value: 'OR'       }]
// [{ field: 'fieldB'      , value: 10         }]
// [{ field: '{{OPERATOR}}', value: 'AND'      }]
// [{ field: 'fieldC'      , value: new Date() }]
// [{ field: '{{OPERATOR}}', value: 'AND'      }]
// [{ field: 'fieldD'      , value: 'valueD'   }]
// [{ field: '{{OPERATOR}}', value: 'OR'       }]
// [{ field: 'fieldE'      , value: 'valueE'   }]

Paginador para consulta de registros

GetAllPaginator<Entity> é uma classe que gerencia o carregamento dos dados paginados, utilizando um serviço que implementa a interface GetAllPaginationService<Entity>. Mantém o estado da consulta.

Propriedade Objetivo
itemsObservable Observable emitido quando os dados são alterados
loadingObservable Observable emitido quando há alteração no modo de carregamento
filters Define os filtros que deverão ser aplicados na consulta
orderBy Define a ordenação que deverá ser aplicada na consulta
page Retorna o número da página atual
pageSize Retorna o número que indica a quantidade de registros a serem carregados por página
items Lista com os dados já carregados
hasNext Indica se a consulta possui uma próxima página
length Quantidade total de registros não considerando a paginação
Método Objetivo
getAll Busca os dados da primeira página
more Busca os dados da próxima página
deleteItem Remove um item da lista de dados já retornados