Giter VIP home page Giter VIP logo

nestjs-monorepo's Introduction

Nestjs-Monorepo

Olá, bom dia, aqui será apresentado uma documentação relativa a estrutura de todas as aplicações que forem criadas dentro desse monorepo, o objetivo dessa documentação é expôr de maneira clara e objetiva o funcionamento da aplicação bem como sua estrutura. Os padrões aqui impostos seguem conceitos como Clean Code, Clean Architecture, SOLID, DRY, KISS e Design Patterns. Essa documentação também tem correlação ao TypeScript Style Guide proposto pelo Google. Uma outra fonte de inspiração foi o repositório Clean Code Typescript, que adapta conceitos conhecidos do Clean Code para o Typescript.

IMPORTANTE

Para rodar esse projeto é necessário o mesmo estar dentro da pasta projects no repositório docker-development para ser executado, para mais informações, favor conferir o Readme do docker-development!

Commitlint, Husky e Commitzen

Instalação do Commitlint:

npm install @commitlint/config-conventional @commitlint/cli --save-dev

É possível gerenciar as configurações do commitlint no arquivo commitlint.config.js

Instalação do Husky:

npm install -g husky
npm install husky@^8.0.3 --save-dev

Adicione o script abaixo do husky no package.json

"scripts": {
  "prepare": "husky install"
}

Para finalizar adicione os arquivos "commit-msg" e "husky.sh" da pasta .husky como hooks; OBS: Em alguns casos sera adicionado um "undefined" no final de ambos arquivos, é necessário remover esse "undefined" de ambos, senão o hook do husky não irá funcionar!

npx husky add .husky/husky.sh
npx husky add .husky/commit-msg
npx husky add .husky/pre-commit
npx husky add .husky/pre-push
npx husky add .husky/open-merge

Instalação do Commitzen:

npm install -g commitizen
npm install commitizen --save-dev
commitizen init cz-conventional-changelog

Adicione o script abaixo do commitzen no package.json

"scripts": {
  "commit": "git-cz"
}

Agora usando o commando "git-cz" será aberta uma interface onde você pode escolher qual o tipo de categoria do commit (feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert); Selecionando a categoria você poderá digitar o escopo que pertence o commit, uma mensagem curta sobre o commit, e caso deseje adicionar mais detalhes também terá a opção de colocar uma descrição;

Caso tenha alguma dúvida ou queira personalizar mais a configuração, segue abaixo o artigo em que foi inspirado a implementação dessas ferramentas:

Padronização de commit com (Commitlint, Husky e Commitizen)

Swagger

Rota do swagger de todas as aplicações do monorepo é sempre o virtual host definido no docker-compose dentro da pasta .docker do docker-development com o sufixo "/docs" no final!

Libs

Para baixar todas as libs do projeto, rodar o comando abaixo

git submodule update --init

Principais Ferramentas

Principais ferramentas utilizadas:

Estrutura

O Projeto segue o seguinte modelo de orgranização de arquivos e pastas:

    /...
    /src
      |__/common
        |__/config
        |__/enum
      |__/module
        |__/moduleName
          |__/application
            |__/controller
            |__/dto
          |_/domain
            |_/contract
            |_/entity
            |_/service
          |_/infra
            |_/repository
            |_/adapter
            |_/schema
    /...
  • /src - Aqui se localiza a raíz da aplicação em questão;

  • /common - Aqui é armazendo pastas contendo arquivos cuja finalidade é utilizá-los na aplicação como um todo independente do seu local;

    • /config - Local os se localiza o mapeamento das variáveis de ambiente(env) da aplicação
    • /enum - Essa pasta compreende os enums(identificadores) utilizados na aplicação como um todo
  • /module -> Aqui são armazenados os módulos da aplicação;

  • /module/moduleName/application:

    • /controller - Essa pasta compreende os controllers da aplicação;
    • /dto - Aqui se localiza as definições de entrada(IN) e saída(OUT) dos controllers;
  • /module/moduleName/domain:

    • /service: Compreende principalmente os services da aplicação;
    • /entity - Entidade de conversão de dados, atuando como um de/para para os dados fornecidos pelo Banco de Dados;
    • /contract - Local onde fica definido os métodos(queries) enviadas ao banco de dados;
  • /module/moduleName/infra:

    • /repository: Aqui se localiza as queries executadas no banco de dados;
    • /adapter: Diretório que compreende conexões com provedores de terceiros ou outras aplicações em diferentes contextos;
    • /schema: Local onde são armazenadas as Tabelas e/ou Schemas/Models relativas ao Banco de Dados;

CASO QUEIRA UMA VISUALIZAÇÃO MAIS DIDÁTICA VOCÊ PODE RODAR O COMPODOC COM O COMANDO:

npm run compodoc:build
npm run compodoc:run

ACESSANDO O http://localhost:4000 UMA INTERFACE VISUAL SERÁ APRESENTADA COM A ESTRUTURAÇÃO DE TODOS OS MÓDULOS DO PROJETO!

Testes

  • Neste projeto utilizamos o Jest como framework para a execução de testes unitários e e2e. Todas as configurações utilizadas podem ser encontradas no arquivo jest.config.json presente na raiz do projeto.
  • Os arquivos contendo testes unitários devem estar no mesmo diretório do código de produção. Por padrão, os arquivos de teste devem ter o mesmo nome do arquivo onde está a implementação do que está sendo testado, com a adição do sufixo spec, por exemplo, my-code.service.spec.ts.
  • Os testes e2e ficam no diretório test, na raiz do projeto, e são organizados por módulos. Esse tipo de teste é utilizado para testar o fluxo da aplicação como um todo, fazendo um request para um endpoint e recebendo uma response. Para efetuar requests nos testes e2e é utilizado a lib Supertest em conjunto com o Jest. O nome dos arquivos de teste deve ter o seguinte padrão: nome do módulo + sufixo e2e-spec, como por exemplo, my-module.e2e-spec.ts.
  • Este projeto também está configurado para gerar relatórios de execução de testes e de coverage. Os de execução podem ser encotrados no diretório reports e os de coverage em coverage, ambos na raiz da aplicação.
  • Os seguintes scripts estão configurados para a execução dos testes:
    • test - executa todos os testes da aplicação.
    • test:watch - executa os testes em watch mode.
    • test:staged - executa os testes relacionados aos arquivos da staging area do git.
    • test:cov - executa todos os testes da aplicação e gera o relatório de coverage.
    • test:debug - executa os testes no modo debug.
    • test:e2e - executa os testes e2e.

Husky

O Husky é uma ferramenta utilizada para a criação e execução de git hooks, permitindo executar lint, tests, etc... ao fazer um commit ou push. Neste projeto temos três hooks configurados:

  • commit-msg: Hook executado quando um commit é realizado. Visa validar, juntamente com o commintlint, se todos os commits estão dentro do padrão estabelecido.
  • pre-commit: Hook executado antes de todos os commits. Com o auxílio do lint-staged executa os testes e lint para todos os arquivos que foram alterados.
  • pre-push: Hook executado antes do push para o repositório de origem. É utilizado para rodar os testes e lint de todo projeto antes de confirmar o push para a origem.

Para melhor entendimento do funcionamento dessa biblioteca, basta acessar o guia disponível na documentação oficial do Husky.

Eslint + Prettier + SonarJS

O ESLint/Prettier/SonarJS analisa estaticamente o código da aplicação para encontrar e corrigir problemas de lint rapidamente. Todas as configurações de plugins e regras de lint utilizadas estão no arquivo .eslintrc.js na raiz da aplicação.

Para executar o lint basta rodar o seguinte comando: npm run lint.

Caso queira entender melhor sobre o funcionamento das bibliotecas, recomendamos a consulta em suas documentações oficiais: ESLint, ESLint SonarJS, Prettier.

Padrões de Nomenclatura

  • Use PascalCase para nomes de classes, types e interfaces: MyClass.
  • Use camelCase para nomes de variáveis, funções e métodos: exampleVariable, myFunction().
  • Use kebab-case + nome da pasta para nome dos arquivos: my-code.service.ts,my-code.repository.ts.
  • Para testes, siga o mesmo padrão de nomes de arquivos, com a adição do sufixo spec: my-code.service.spec.ts,my-code.repository.spec.ts.
  • Use snake_case + uppercase para nomes de constantes e enums: MAX_LIMIT, MIN_LIMIT.

Boas Práticas

1. Defina variáveis com nomes pronunciáveis e que façam sentido. Isso também serve para tipos, funções e etc.

Bad:

type DtaRcrd102 = {
  genymdhms: Date;
  modymdhms: Date;
  pszqint: number;
};

Good:

type Customer = {
  generationTimestamp: Date;
  modificationTimestamp: Date;
  recordId: number;
};

2. Defina variáveis com nomes que possam ser lidos e procurados com facilidade.

Bad:

// What the heck is 86400000 for?
setTimeout(restart, 86400000);

Good:

// Declare them as capitalized named constants.
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000; // 86400000

setTimeout(restart, MILLISECONDS_PER_DAY);

3. Evite mapeamento mental. Defina variáveis de forma explicita.

Explicit is better than implicit. Clarity is king. Bad:

const u = getUser();
const s = getSubscription();
const t = charge(u, s);

Good:

const user = getUser();
const subscription = getSubscription();
const transaction = charge(user, subscription);

4. Use argumentos default ao invés de condicionais ou ternários.

Bad:

function loadPages(count?: number) {
  const loadCount = count !== undefined ? count : 10;
  // ...
}

Good:

function loadPages(count: number = 10) {
  // ...
}

5. Use enums para documentar a intenção do código.

Bad:

const GENRE = {
  ROMANTIC: 'romantic',
  DRAMA: 'drama',
  COMEDY: 'comedy',
  DOCUMENTARY: 'documentary',
};

configureFilm(GENRE.COMEDY);

Good:

enum GENRE {
  ROMANTIC,
  DRAMA,
  COMEDY,
  DOCUMENTARY,
}

configureFilm(GENRE.COMEDY);

6. Limite a quantidade de paramêtros de uma função/método para no máximo 2

Bad:

function createMenu(
  title: string,
  body: string,
  buttonText: string,
  cancellable: boolean,
) {
  // ...
}

createMenu('Foo', 'Bar', 'Baz', true);

Good:

type MenuOptions = {
  title: string;
  body: string;
  buttonText: string;
  cancellable: boolean;
};

function createMenu(options: MenuOptions) {
  // ...
}

createMenu({
  title: 'Foo',
  body: 'Bar',
  buttonText: 'Baz',
  cancellable: true,
});

7. Funções/métodos devem ter uma única responsabilidade.

Bad:

function emailActiveClients(clients: Client[]) {
  clients.forEach((client) => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()) {
      email(client);
    }
  });
}

Good:

function emailActiveClients(clients: Client[]) {
  clients.filter(isActiveClient).forEach(email);
}

function isActiveClient(client: Client) {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
}

8. Nomes de funções/métodos devem dizer exatamente o que fazem.

Bad:

function addToDate(date: Date, month: number): Date {
  // ...
}

const date = new Date();

// It's hard to tell from the function name what is added
addToDate(date, 1);

Good:

function addMonthToDate(date: Date, month: number): Date {
  // ...
}

const date = new Date();
addMonthToDate(date, 1);

Referências

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.