<img src="https://i.imgur.com/LL8vlPz.png=x100" width="400" style="margin-left: auto;margin-right: auto; display: block;" />
<div style="margin-top: 20px; margin-left: auto; margin-right: auto; display: block; width: 500px;" >
<img src="https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg" alt="Semantic Release" />
<img src="https://img.shields.io/badge/pnpm-v7.0.0-blue" alt="Yarn version" />
<img alt="Node version" src="https://img.shields.io/badge/node-16%2B-green">
<img alt="License" src="https://img.shields.io/badge/license-MIT-%238257E6">
<img alt="BFF" src="https://img.shields.io/badge/Architecture-BFF-yellow">
</div>
## Sumário
1. **[Introdução](#Introdução)**
2. **[Estrutura do projeto](#Estrutura-do-projeto)**
3. **[Principais dependências](#Principais-dependências)**
4. **[Padrões utilizados](#Padrões-utilizados)**
5. **[Testes](#Testes)**
6. **[Padrões de estilo](#Padrões-de-estilo)**
7. **[Inicializando a aplicação](#Inicializando-a-aplicação)**
8. **[Como contribuir](#Como-contribuir)**
9. **[Changelog](#Changelog)**
10. **[Artigos que podem ajudar](#Artigos-que-podem-ajudar)**
## Introdução
O gestor de conteúdo é uma plataforma de cadastro e gestão, que visa dar autonomia para as equipes de conteúdo de digital, que atualmente têm dificuldade em cadastrar e gerenciar diversos tipos de conteúdos.
Seu objetivo é fornecer uma forma de cadastro centralizado, organizado e rápido. Permitindo facilidade na consulta e reutilização dos conteúdos.
## Estrutura do projeto
A estrutura do projeto segue o padrão monorepo, com design pattern inspirado no Clean Code. Nosso objetivo nessa estrutura é garantir escalabilidade e evitar redundância de código dentro do projeto. Também utilizando a arquitetura Microfrontend para que o acoplamento e desacoplamento de módulos e partes do projeto sejam possíveis sem a necessidade de uma refatoração futura, evitando assim um re-trabalho.
```
gestor-de-conteudo/
├─ .husky/
├─ docs/
├─ packages/
│ ├─ apps/
│ │ ├─ core/
│ │ │ ├─ public/
│ │ │ │ ├─ index.html
│ │ │ ├─ src/
│ │ │ ├─ tools/
│ │ │ │ ├─ app.prod.json
│ │ │ ├─ .microfrontendrc
│ │ │ ├─ tsconfig.json
│ │ ├─ login/
│ │ ├─ web/
│ ├─ commons/
│ │ ├─ api/
│ │ ├─ modules/
│ │ ├─ ui/
│ │ ├─ utils/
│ ├─ config/
│ │ ├─ build/
│ │ ├─ eslint/
│ │ ├─ test/
│ │ ├─ tsconfig/
├─ scripts/
│ ├─ upload-sourcemap.js
├─ .cz
├─ .editorconfig
├─ .gitignore
├─ jest.mapper.js
├─ .lintstagedrc.json
├─ commitlint.config.js
├─ package.json
├─ pnpm-workspace.yaml
├─ prettier.config.js
├─ readme.md
├─ turbo.json
```
> Estrutura base do gestor de conteúdos
### Pacotes de configuração (config)
Esse pacote contém as seguintes configurações:
- **build**: Configurações de build da aplicação.
- **variáveis de ambiente**: Configurações das variáveis de ambiente da aplicação.
- **eslint**: Configurações de eslint para os pacotes.
- **testes**: Configurações de testes para os pacotes.
- **tsconfig**: Configurações de TypeScript para os pacotes.
Elas foram separadas em um pacote único visando evitar redundâncias, pois, dessa forma, ao invés de realizar cada uma dessas configurações em cada um dos outros pacotes que precisarem delas, podemos apenas realizar as importações necessárias.
### Pacotes de aplicação (apps)
Esse pacote contempla todos os **microfrontends** que constituem a aplicação, são eles:
- **core**: Centraliza os demais microfrontends, é ele quem consome as outras aplicações.
- **login**: Responsável pelo login na aplicação. Ele foi desacoplado para que, caso haja alguma alteração de responsabilidades e o processo de login no **Gestor** passe a ser feito por outra tribo, seja fácil realizar alterações e consumir esse novo formato de login.
- **web**: Contém o restante da aplicação, onde o usuário irá gerenciar os conteúdos cadastrados.
### Pacotes compartilhados (commons)
Os pacotes compartilhados centralizam funções utilitárias e componentes que podem ser úteis nos demais pacotes. Mais uma vez a ideia é evitar redundâncias e consumir tudo de apenas um lugar, assim facilitando a manutenção.
Atualmente os seguintes pacotes são compartilhados:
- **api**: Responsável expor os serviços que se comunicam com a API.
- **modules**: Centraliza os estados da aplicação e suas funções de manipulação.
- **ui**: Exporta para os demais pacotes os componentes que serão usados no desenvolvimento dos apps.
- Semelhante ao **microfrontend de login**, foi isolado em um pacote para caso haja alguma alteração e seja necessário consumir outros componentes, como, por exemplo, o Design System da ArcoTech, seja possível realizar essa alteração de forma simples.
- **utils**: Contém funções utilitárias e de comum uso entre os pacotes.
## Principais dependências
**[turborepo](https://turborepo.org/):** Turborepo tem como principal competência o fácil manuseio dos pacotes gerados dentro de uma estrutura monorepo. Turborepo foi escolhido com o objetivo de garantir a agilidade e o desempenho dentro do projeto.
**[zustand](https://github.com/pmndrs/zustand):** Uma solução de gerenciamento de estado de bearbones pequena, rápida e escalável usando princípios de fluxo simplificados.
**[craco](https://github.com/gsoft-inc/craco):** É uma ferramenta que possibilita fazer re-esctritas dentro do react-app sem a necessidade de realizar um eject. Utilizado para implementar o MCF dentro das soluções.
**[tsdx](https://tsdx.io/):** É uma CLI de configuração zero que ajuda você a desenvolver, testar e publicar pacotes modernos do TypeScript com facilidade.
**[express](https://expressjs.com/pt-br/):** É um framework para aplicativo da web do Node.js mínimo e flexível que fornece um conjunto robusto de recursos para aplicativos web e móvel.
**[react](https://pt-br.reactjs.org/):** Uma biblioteca para criação de UIs interativas.
## Padrões utilizados
Visando manter a organização, e um mínimo de qualidade, o desenvolvimento deste projeto conta com a aplicação de alguns padrões:
O versionamento do projeto segue o modelo de branches de [Vincent Driessen](https://nvie.com/posts/a-successful-git-branching-model/), aplicado com o uso do [Git Flow](https://danielkummer.github.io/git-flow-cheatsheet/index.pt_BR.html).
A criação de novas branches deverá ser feita através da CLI do Git Flow, cujos comandos estão expressos no cheatset do link acima.
A nomenclatura das branches respeita o padrão declarativo do projeto a depender do propósito da modificação trazida em seu conteúdo, iniciando com:
- `Feature`
- `Bugfix`
- `Hotfix`
- `Release`
Os commits no repositório estarão sujeitos à análise do [Husky](https://www.npmjs.com/package/husky), devendo respeitar as regras de estilo, os testes do projeto e por fim à padronização das mensagens de commit utilizadas no versionamento.
Caso queira utilizar o CLI do Husky, deverá seguir o fluxo gerado e após avançar pelas etapas da interface, será gerado um commit personalizado de acordo com o padrão esperado no projeto.
### Regras semânticas de estilo de código
O projeto conta com padronização de estilo própria. É necessário estar de acordo com as regras de estilo para que seja possível realizar um commit, caso contrário a modificação ficará travada na fase _lint staged_ do Husky.
## Testes
A aplicação de testes são sempre muito importantes dentro de um projeto para garantir a integridade e a fidelidade daquilo que estamos desenvolvendo. O Gestor de Conteúdos conta com um módulo central de configuração de testes, utilizando como motor o [jest](https://jestjs.io/pt-BR/).
### Criando um teste
Para criar um teste é simples, seja para um novo pacote gerado dentro do projeto ou para um pacote atual. O módulo `@content-manager/test` não precisa ser instalado pois já está configurado globalmente dentro da aplicação. Ele exporta diversas funções comumente utilizadas para renders e manipulação de eventos. Para utilizar qualquer função do **@testing-library** basta importar o módulo de test.

**obs:** Para novos pacotes criados o comando de `test` deve ser em comum para todo o projeto, como mostra no exemplo abaixo:
```json=
"scripts": {
"test": "manager-test"
},
"devDependencies": {
"@content-manager/test": "workspace:*"
},
```
### O que é testado dentro do projeto?
Basicamente tudo. Dentro da estrutura do projeto, a única parte que não necessita de uma estrutura de teste são os módulos de configuração, pois estes fazem parte do fluxo de desenvolvimento do front e não faz parte do código de build final. Então, criou um novo modulo que não é de configuração? Aplica teste nesse carinha ❤️.
### Coverage
Buscamos sempre a excelência em todo o processo de criação e desenvolvimento dentro do gestor de conteúdo, por esse e outros motivos temos uma régua alta para o coverage a aplicação. A taxa de aceitação do projeto é de **80%**, mas logicamente, esperamos sempre manter em 100%. Lembrando que, quanto mais testes, menor o risco de problemas futuros.
**Coverage folder:** a pasta de coverage fica na raiz do projeto e **não deve fazer parte do commit**. Dentro dela vamos encontrar todos os testes da aplicação a fim de facilitar a vida do dev para mapear os testes que já foram aplicados em todo o projeto.
**SonarCloud:** Seu melhor amigo...ou não! Utilizamos o Sonar como um ***double check*** para os nossos testes. Além disso o Sonar ajuda a garantir não-redundância de códigos assim como o cumprimento de algumas regras de padrões dentro do fluxo de desenvolvimento.
### Erro comum no Jest (jest mapper)
Como estamos em uma estrutura monorepo, com aplicação de microfrontends e um módulo global de configuração de testes, é super comum o Jest dar uma de maluco e não conseguir resolver alguns pacotes internos que estamos utilizando dentro do fluxo de desenvolvimento. Para isso criamos um arquivo chamado `jest.mapper.js` esse carinha fica responsável por dizer ao jest como ele vai encontrar algum pacote que ele esta tendo dificuldade em resolver, deu pra entender?
Bora ver um exemplo:

## Inicializando a aplicação
Mesmo com tantos padrões e conceitos aplicados dentro do projeto, configurar o ambiente de desenvolvimento é um tarefa fácil, isso por que estamos falando de uma aplicação que utiliza o **node** como motor.
### Do zero ao build
Para que você possa iniciar no desenvolvimento da aplicação, tenha o node instalado e atualizado em sua ultima versão, e o gerenciador de pacotes também instalado.
Com tudo devidamente configurado dentro do seu ambiente de desenvolvimento, clone o repositório da aplicação:
```bash
git clone git@github.com:arcotech-services/content-manager-web.git
```
Entre na pasta `content-manager-web` e inicie a instalação dos pacotes dentro do projeto.
É importante lembra que, estamos utilizando o **pnpm** para orquestrar a estrutura monorepo, por isso é necessário utilizá-lo para instalação e gerencia dos pacotes.
```bash
pnpm i
```
Para rodar o projeto em ambiente de desenvolvimento basta rodar `pnpm dev` e todos os pacotes serão preparados. o Turborepo garante que tenhamos um paralelismo, ou seja, ambientes multi-dinâmicos, o que garante maior agilidade no controle e na inicialização de cada pacote interno.
**Rodar um projeto individualmente**: Caso você queira debugar mais a fundo alguma funcionalidade, ou queira focar sua atenção em um único modulo, você pode fazer da seguinte forma:
```bash
cd packages/__folder/__module__ && pnpm dev
# ou pode rodar da pasta root
pnpm --prefix packages/__folder/__module__ dev
```
esses comando seguem um padrão, então julgamos não ser necessário apresenta-los um por um aqui na documentação, mas você pode conferir todos os comando configurados acessando o arquivo `package.json` presente no root.
### CI & CD
Nossas configurações de CI & CD seguem o padrão de Action do github e esta localizado na pasta `.github`. Separamos responsabilidades dentro da CI, então é comum ter uma pasta **templates** onde terão arquivos configuracionais que são comumente repetidos ao longo do fluxo de construção da CI.
### Pull Request
Nenhum código é aceito sem um code reviewer, isso por que presamos pela qualidade do que estamos entregando. Na finalização de um atividade, uma PR deverá ser aberta para o ramo em questão (develop), um template PR será apresentado com alguns questionamentos e um checklist que deve ser seguido para garantirmos uma padronização e gerarmos uma documentação de atividades desenvolvidas vs discusões geradas em cada PR.
### Gerenciador de pacotes (pnpm)
O **pnpm** é um gerenciador de pacotes alternativo para Node.js. É um substituto imediato para o npm, mas mais rápido e eficiente.
Diferente dos demais gerenciadorres de pacote, o **pnpm** só instala uma dependência uma vez. Dessa forma, os projetos podem compartilhar dependências e economizando muito espaço em disco.
Para instalá-lo em sua máquina, basta seguir as intruções apresentadas na [documentação](https://pnpm.io/pt/installation).
### Como instalar/remover uma dependência
#### Instalando uma dependência
O processo de instalação de uma dependência é bem simples. Primeiro certifique-se que se encontra dentro do **pacote** em que se deseja realizar a adição e então execute o comando `pnpm add nome-do-pacote`.
Depois de realizar a instalação da nova dependência, você deve executar o comando `pnpm i` para que o **pnpm** possa resolver a instalação feita e atualizar o **pnpm-lock.yaml**.
Imagine que você deseja adicionar um nova dependência ao pacote **web**, você deverá fazer da seguinte forma:
```bash=
pwd
# /content-manager-web
cd packages/apps/web
# /content-manager-web/packages/apps/web
pnpm add styled-components
pnpm i
```
#### Removendo uma dependência
O processo de remoção de uma dependência é semelhante ao processo de instalação, mas nesse cenário você deverá executar o comando `pnpm remove`. **Lembre-se que é importante estar dentro do pacote correto!**
Considere agora que a dependência que você instalou no pacote **web** não será mais utilizada, para removê-la você seguirá os seguintes passos:
```bash=
pwd
# /content-manager-web/packages/apps/web
pnpm remove styled-components
pnpm i
```
Mais uma vez é importante que você o comando `pnpm i` para resolução do pacote removido e atualização do **pnpm-lock.yaml**.
Caso queira saber mais sobre os comandos do **pnpm** você pode consultar a [documentação](https://pnpm.io/pt/cli/add) e se profundar no assunto!
### Variáveis de ambiente
É importante que as [variáveis de ambiente](https://dev.to/guiselair/utilizando-variaveis-de-ambiente-com-create-react-app-5ckc) do projeto sejam configuradas, pois, por padrão, elas não vêm configuradas na clonagem do repositório.
No diretório `packages/config/environments` você encontrará o arquivo `.env.example`. Ele é um exemplo de como o seu arquivo `.env` deve ser.
Faça uma copia de `.env.example` dentro de `packages/config/environments` e renomeie para `.env`. Então **preencha todas as variáveis**.
Exemplo de uma variável de ambiente preenchida corretamente:
```
PUBLIC_URL='http://localhost:3000'
```
As variáveis são tipadas para facilitar na utilização dentro do fluxo de desenvolvimento, então caso necessário adição de um novo valor, é importante lembrar de atualizar os tipos também com a nova chave.

> obs: Não é necessário utilizar o prefixo **REACT_APP** para a declaração de uma nova variável, isso por que realizamos a injeção delas antes do projeto ser preparado para os ambientes (dev/prod).
### Micro frontend
Utilizamos a arquitetura de microfrontends dentro do gerenciador de conteúdos para garantir um facil (des)acoplamento dos apps desenvolvidos dentro da estrutura. A configuração dos microfrontends é feita utilizando o [webpack Module Federation](https://webpack.js.org/concepts/module-federation/).
**core**: Nela fica as principais configurações do projeto, as rotas condicionais e a ligação entre microfrontends acontecem aqui. Bem como componentes que se repetem de forma continua ( header, footer e etc ).
**login**: Como o próprio nome já diz, aqui fica os steps que antecedem o ambiente logado.
**web**: Com o login já estabelecido, o módulo web é o ambiente logado da aplicação, contém toda a estrutura do gestor.
O Microfrontend é configurado utilizando o craco, e esta centralizado em `config/build`. Cada módulo MCF contem um arquivo **.microfrontendrc** que retêm algumas configurações cruciais para o pleno funcionamento da aplicação.

Dentro de **core** é onde consumimos os outros microfrontends, e para que esse consumo seja feito tempos uma estrutura criada para consumi-los.
```bash
├─ core/
│ ├─ public/
│ ├─ index.html
│ ├─ src/
│ ├─ tools/
│ │ ├─ app.prod.json
│ │ ├─ app.common.json
│ ├─ .microfrontendrc
│ ├─ tsconfig.json
```
**tools folder**: A Pasta `tools` contém 3 arquivos que são necessários para a configuração de consumo dos microfrontends. Caso queira consumir um microfrontend em outro pacote, replique a estrutura.

> Exemplo de configuração para consumo dos microfrontends de login e web.
Na estrutura que temos definido para o projeto, o consumo dos microfrontends depois de configurado se assemelha ao módulo.
Como estamos utilizando typescript, e os modulos de MCF não contém tipagens pré estabelecidas, precisamos declara-las, e para isso é necessário incluir o modulo num arquivo de definição de tipos como mostra no exemplo:
```typescript
// file: core/@types/global.d.ts
declare module 'content-manager-login/Login'
declare module 'content-manager-web/Web'
```
Com as definições feitas, já podemos consumir os microfrontends. Indicamos ler os artigos que indicamos abaixo para entender o fluxo do Webpack e como os MCF se resolvem dentro da aplicação.

## Como contribuir
No arquivo `docs/CONTRIBUTING.md` presente na raiz do projeto encontra-se a explicação de como contribuir com o projeto, desde como ajudá-lo a melhorar diretamente a como enviar feedback.
## Changelog
O histórico de alterações no código encontra-se no arquivo `docs/CHANGELOG.md`, este arquivo possui todas as features, bug fixes, hot fixes e releases e está na raiz do projeto.
---
### Idealizadores ✨
<table>
<tr>
<td align="center"><a href="https://github.com/MatheusKindrazki"><img src="https://avatars.githubusercontent.com/u/36010251?v=4?s=64" width="64px;" alt=""/><br /><sub><b>Matheus Kindrazki</b></sub></a><br /><a href="#!" title="Code">💻</a> <a href="#!" title="Maintenance">🚧</a> <a href="#!" title="Documentation">📖</a> <a href="#!" title="Examples">💡</a></td>
<td align="center"><a href="https://github.com/gomesanac"><img src="https://avatars.githubusercontent.com/u/60011712?v=4?s=64" width="64px;" alt=""/><br /><sub><b> Ana Carolina </b></sub></a><br /><a href="#!" title="Code">💻</a> <a href="#!" title="Maintenance">🚧</a> <a href="#!" title="Documentation">📖</a> <a href="#!" title="Examples">💡</a></td>
</tr>
</table>
## Artigos que podem ajudar
Depois de ler todo esse conteúdo, algumas dúvida acabam surgindo, e para isso juntamos vários artigos para que fique fácil assimilar essa chuva de conceitos dentro desse projeto 🤣🤣
1. [Microfrontends with Module Federation: What, Why, and How](https://levelup.gitconnected.com/microfrontends-with-module-federation-what-why-and-how-845f06020ee1)
2. [Turborepo Walkthrough](https://www.youtube.com/watch?v=YX5yoApjI3M&ab_channel=Vercel)
3. [Facade - Design Pattern](https://refactoring.guru/pt-br/design-patterns/facade)
4. [Monorepo vs Multi-Repo](https://kinsta.com/pt/blog/monorepo-vs-multi-repo/)
5. [Clean code de forma rápida](https://blog.betrybe.com/tecnologia/clean-code/)
6. [Webpack Module Federation](https://webpack.js.org/concepts/module-federation/)