innovationhub-cli 1.1.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -86
  3. package/index.js +228 -29
  4. package/package.json +12 -3
  5. package/templates/nest/.env.example +41 -0
  6. package/templates/nest/.prettierrc +4 -0
  7. package/templates/nest/Dockerfile +17 -0
  8. package/templates/nest/README.md +224 -0
  9. package/templates/nest/addons/.github/dependabot.yml +11 -0
  10. package/templates/nest/addons/.github/labeler.yml +34 -0
  11. package/templates/nest/addons/.github/workflows/check-branch.yml +24 -0
  12. package/templates/nest/addons/.github/workflows/ci.yml +29 -0
  13. package/templates/nest/addons/.github/workflows/draft-release.yml +22 -0
  14. package/templates/nest/addons/.github/workflows/pr-labeler.yml +16 -0
  15. package/templates/nest/addons/.github/workflows/release.yml +33 -0
  16. package/templates/nest/addons/.github/workflows/security-audit.yml +17 -0
  17. package/templates/nest/addons/.github/workflows/semantic-pr.yml +31 -0
  18. package/templates/nest/addons/.github/workflows/stale.yml +24 -0
  19. package/templates/nest/addons/.husky/commit-msg +17 -0
  20. package/templates/nest/addons/.husky/pre-commit +1 -0
  21. package/templates/nest/addons/addons.json +17 -0
  22. package/templates/nest/addons/cloudinary/cloudinary.module.ts +11 -0
  23. package/templates/nest/addons/cloudinary/cloudinary.provider.ts +16 -0
  24. package/templates/nest/addons/cloudinary/cloudinary.service.ts +54 -0
  25. package/templates/nest/docker-compose.yml +58 -0
  26. package/templates/nest/eslint.config.mjs +34 -0
  27. package/templates/nest/jest.config.js +17 -0
  28. package/templates/nest/nest-cli.json +12 -0
  29. package/templates/nest/package.json +99 -0
  30. package/templates/nest/src/app.controller.ts +7 -0
  31. package/templates/nest/src/app.module.ts +69 -0
  32. package/templates/nest/src/app.service.ts +4 -0
  33. package/templates/nest/src/auth/auth.controller.ts +97 -0
  34. package/templates/nest/src/auth/auth.module.ts +46 -0
  35. package/templates/nest/src/auth/auth.service.ts +231 -0
  36. package/templates/nest/src/auth/decorators/roles.decorator.ts +5 -0
  37. package/templates/nest/src/auth/dto/change-password.dto.ts +21 -0
  38. package/templates/nest/src/auth/dto/login-response.dto.ts +25 -0
  39. package/templates/nest/src/auth/dto/login.dto.ts +15 -0
  40. package/templates/nest/src/auth/dto/refresh-token.dto.ts +12 -0
  41. package/templates/nest/src/auth/entities/refresh-token.entity.ts +18 -0
  42. package/templates/nest/src/auth/enums/role.enum.ts +4 -0
  43. package/templates/nest/src/auth/guards/jwt-auth.guard.ts +5 -0
  44. package/templates/nest/src/auth/guards/refresh-token.guard.ts +5 -0
  45. package/templates/nest/src/auth/guards/roles.guard.ts +23 -0
  46. package/templates/nest/src/auth/interfaces/jwt-payload.interface.ts +10 -0
  47. package/templates/nest/src/auth/strategies/jwt.strategy.ts +28 -0
  48. package/templates/nest/src/auth/strategies/local.strategy.ts +23 -0
  49. package/templates/nest/src/auth/strategies/refresh-token.strategy.ts +32 -0
  50. package/templates/nest/src/common/base.entity.ts +19 -0
  51. package/templates/nest/src/common/base.repository.ts +79 -0
  52. package/templates/nest/src/common/base.service.ts +28 -0
  53. package/templates/nest/src/common/constants/errors.constants.ts +33 -0
  54. package/templates/nest/src/common/decorators/user.decorator.ts +9 -0
  55. package/templates/nest/src/common/dto/base-query.dto.ts +56 -0
  56. package/templates/nest/src/common/irepository.ts +18 -0
  57. package/templates/nest/src/common/utils/duration.utils.ts +33 -0
  58. package/templates/nest/src/common/utils/pagination.utils.ts +35 -0
  59. package/templates/nest/src/common/utils/slug.utils.ts +14 -0
  60. package/templates/nest/src/common/utils/transform.utils.ts +62 -0
  61. package/templates/nest/src/common/validators/is-date-after.validator.ts +40 -0
  62. package/templates/nest/src/data-source.ts +23 -0
  63. package/templates/nest/src/main.ts +44 -0
  64. package/templates/nest/src/user/dto/create-user.dto.ts +50 -0
  65. package/templates/nest/src/user/dto/query-users.dto.ts +23 -0
  66. package/templates/nest/src/user/dto/update-user.dto.ts +15 -0
  67. package/templates/nest/src/user/entities/user.entity.ts +66 -0
  68. package/templates/nest/src/user/user.controller.ts +172 -0
  69. package/templates/nest/src/user/user.module.ts +15 -0
  70. package/templates/nest/src/user/user.repository.ts +61 -0
  71. package/templates/nest/src/user/user.service.ts +138 -0
  72. package/templates/nest/template.json +5 -0
  73. package/templates/nest/test/jest-e2e.json +12 -0
  74. package/templates/nest/tsconfig.build.json +4 -0
  75. package/templates/nest/tsconfig.json +25 -0
  76. package/templates/python/.env.example +37 -0
  77. package/templates/python/Dockerfile +18 -0
  78. package/templates/python/README.md +219 -0
  79. package/templates/python/addons/.github/dependabot.yml +11 -0
  80. package/templates/python/addons/.github/labeler.yml +29 -0
  81. package/templates/python/addons/.github/workflows/check-branch.yml +24 -0
  82. package/templates/python/addons/.github/workflows/ci.yml +30 -0
  83. package/templates/python/addons/.github/workflows/draft-release.yml +22 -0
  84. package/templates/python/addons/.github/workflows/pr-labeler.yml +16 -0
  85. package/templates/python/addons/.github/workflows/release.yml +30 -0
  86. package/templates/python/addons/.github/workflows/security-audit.yml +21 -0
  87. package/templates/python/addons/.github/workflows/semantic-pr.yml +31 -0
  88. package/templates/python/addons/.github/workflows/stale.yml +24 -0
  89. package/templates/python/addons/addons.json +17 -0
  90. package/templates/python/addons/cloudinary/service.py +67 -0
  91. package/templates/python/addons/pre-commit/.pre-commit-config.yaml +31 -0
  92. package/templates/python/alembic/env.py +56 -0
  93. package/templates/python/alembic/script.py.mako +26 -0
  94. package/templates/python/alembic/versions/.gitkeep +0 -0
  95. package/templates/python/alembic.ini +39 -0
  96. package/templates/python/app/__init__.py +0 -0
  97. package/templates/python/app/auth/__init__.py +5 -0
  98. package/templates/python/app/auth/dependencies.py +118 -0
  99. package/templates/python/app/auth/enums.py +6 -0
  100. package/templates/python/app/auth/models.py +18 -0
  101. package/templates/python/app/auth/router.py +68 -0
  102. package/templates/python/app/auth/schemas.py +58 -0
  103. package/templates/python/app/auth/service.py +180 -0
  104. package/templates/python/app/common/__init__.py +18 -0
  105. package/templates/python/app/common/base_model.py +26 -0
  106. package/templates/python/app/common/base_repository.py +83 -0
  107. package/templates/python/app/common/errors.py +35 -0
  108. package/templates/python/app/common/pagination.py +22 -0
  109. package/templates/python/app/common/schemas.py +20 -0
  110. package/templates/python/app/common/utils.py +15 -0
  111. package/templates/python/app/core/__init__.py +4 -0
  112. package/templates/python/app/core/config.py +55 -0
  113. package/templates/python/app/core/database.py +20 -0
  114. package/templates/python/app/main.py +33 -0
  115. package/templates/python/app/user/__init__.py +4 -0
  116. package/templates/python/app/user/models.py +26 -0
  117. package/templates/python/app/user/repository.py +84 -0
  118. package/templates/python/app/user/router.py +170 -0
  119. package/templates/python/app/user/schemas.py +60 -0
  120. package/templates/python/app/user/service.py +114 -0
  121. package/templates/python/docker-compose.yml +55 -0
  122. package/templates/python/pyproject.toml +46 -0
  123. package/templates/python/requirements-dev.txt +7 -0
  124. package/templates/python/requirements.txt +20 -0
  125. package/templates/python/template.json +5 -0
  126. package/utils/template.js +165 -0
  127. package/utils/git.js +0 -71
@@ -0,0 +1,224 @@
1
+ # Template NestJS — Innovation Hub
2
+
3
+ Template base para inicialização de projetos backend com **NestJS**. Inclui autenticação completa, gerenciamento de usuários e uma estrutura modular pronta para expandir.
4
+
5
+ ## ✨ Funcionalidades Incluídas
6
+
7
+ - **Autenticação e Autorização**: Sistema completo de login com JWT (JSON Web Tokens), refresh tokens rotativos e controle de acesso baseado em papéis (Roles).
8
+ - **Gerenciamento de Usuários**: CRUD de usuários com criptografia de senhas (bcrypt), soft delete, paginação e reset de senha por admin.
9
+ - **Base Genérica Reutilizável**: `BaseEntity`, `BaseRepository`, `BaseService` e `IRepository` para criar novos módulos rapidamente.
10
+ - **Documentação de API**: Geração automática de documentação interativa com **Swagger (OpenAPI)**.
11
+ - **Envio de E-mails**: Serviço de e-mail configurável com templates Handlebars.
12
+ - **Utilitários**: Paginação, geração de slugs, parsing de duração, validadores customizados e constantes de erro centralizadas.
13
+
14
+ ## 🚀 Tecnologias Utilizadas
15
+
16
+ - **Framework**: [NestJS](https://nestjs.com/)
17
+ - **Linguagem**: [TypeScript](https://www.typescriptlang.org/)
18
+ - **Banco de Dados**: [PostgreSQL](https://www.postgresql.org/)
19
+ - **ORM**: [TypeORM](https://typeorm.io/)
20
+ - **Containerização**: [Docker](https://www.docker.com/) e Docker Compose
21
+ - **Autenticação**: [Passport.js](http://www.passportjs.org/) (Estratégias `local`, `jwt` e `jwt-refresh`)
22
+ - **Validação de Dados**: `class-validator` e `class-transformer`
23
+ - **Testes**: [Jest](https://jestjs.io/) para testes unitários e E2E.
24
+
25
+ ---
26
+
27
+ ## 🏁 Como Começar
28
+
29
+ Siga os passos abaixo para configurar e executar o projeto em seu ambiente local.
30
+
31
+ ### Pré-requisitos
32
+
33
+ - [Node.js](https://nodejs.org/en/) (v18 ou superior)
34
+ - [Docker](https://www.docker.com/get-started) e Docker Compose
35
+ - [NPM](https://www.npmjs.com/)
36
+
37
+ ### 1. Clone o Repositório
38
+
39
+ ```bash
40
+ git clone <URL_DO_REPOSITORIO>
41
+ cd <NOME_DO_PROJETO>
42
+ ```
43
+
44
+ ### 2. Configure as Variáveis de Ambiente
45
+
46
+ Copie o arquivo de exemplo `.env.example` para um novo arquivo chamado `.env` e preencha as variáveis.
47
+
48
+ ```bash
49
+ # No Windows (prompt de comando)
50
+ copy .env.example .env
51
+
52
+ # No Linux ou macOS
53
+ cp .env.example .env
54
+ ```
55
+
56
+ Abra o arquivo `.env` e preencha todas as variáveis necessárias, como as credenciais do banco de dados e segredos do JWT. Para o ambiente Docker padrão, as credenciais do Postgres já vêm configuradas no `docker-compose.yml`.
57
+
58
+ ### 3. Instale as Dependências
59
+
60
+ ```bash
61
+ npm install
62
+ ```
63
+
64
+ ---
65
+
66
+ ## 🐳 Executando com Docker (Recomendado)
67
+
68
+ O projeto está configurado para rodar facilmente com Docker, simplificando a configuração do banco de dados e da API.
69
+
70
+ ### Subir o Ambiente de Desenvolvimento
71
+
72
+ ```bash
73
+ docker-compose --profile dev up -d --build
74
+ ```
75
+
76
+ ### Subir o Ambiente de Produção
77
+
78
+ ```bash
79
+ docker-compose --profile prod up -d --build
80
+ ```
81
+
82
+ - A API estará disponível em `http://localhost:3000`.
83
+ - O banco de dados PostgreSQL estará acessível na porta `5432`.
84
+
85
+ ### Parar o Ambiente
86
+
87
+ ```bash
88
+ docker-compose down
89
+ ```
90
+
91
+ ---
92
+
93
+ ## ⚙️ Executando Localmente (Sem Docker)
94
+
95
+ ### 1. Execute um Banco de Dados PostgreSQL
96
+
97
+ Garanta que você tenha uma instância do PostgreSQL rodando e que as credenciais no seu arquivo `.env` apontem para ela.
98
+
99
+ ### 2. Execute as Migrations
100
+
101
+ ```bash
102
+ npm run migration:run
103
+ ```
104
+
105
+ ### 3. Inicie a Aplicação
106
+
107
+ ```bash
108
+ # Modo de desenvolvimento com hot-reload
109
+ npm run start:dev
110
+ ```
111
+
112
+ A aplicação estará disponível em `http://localhost:3000`.
113
+
114
+ ---
115
+
116
+ ## 📄 Documentação e Endpoints
117
+
118
+ ### Acessar a Documentação
119
+
120
+ Com a aplicação em execução, acesse a documentação interativa da API gerada pelo Swagger em:
121
+ **[http://localhost:3000/api/docs](http://localhost:3000/api/docs)**
122
+
123
+ ### Resumo dos Endpoints Principais
124
+
125
+ - `POST /auth/login`: Autentica um usuário e retorna tokens JWT.
126
+ - `POST /auth/logout`: Faz logout (revoga refresh token).
127
+ - `POST /auth/refresh`: Atualiza os tokens de acesso usando um refresh token.
128
+ - `PATCH /auth/change-password`: Altera a senha do usuário logado.
129
+ - `GET /users/me`: Retorna o perfil do usuário autenticado.
130
+ - `PATCH /users/me`: Atualiza o perfil do usuário autenticado.
131
+ - `GET /users`: Lista todos os usuários (admin).
132
+ - `GET /users/paginated`: Lista usuários com paginação e busca (admin).
133
+ - `GET /users/:id`: Busca um usuário pelo ID (admin).
134
+ - `POST /users`: Cria um novo usuário (admin).
135
+ - `PATCH /users/:id`: Atualiza um usuário pelo ID (admin).
136
+ - `PATCH /users/:id/reset-password`: Reseta a senha de um usuário (admin).
137
+ - `DELETE /users/:id`: Deleta um usuário (admin).
138
+
139
+ ---
140
+
141
+ ## 📂 Estrutura do Projeto
142
+
143
+ ```
144
+ src/
145
+ ├── auth/ # Autenticação: estratégias (JWT, local, refresh), guards, decorators, DTOs
146
+ ├── common/ # Base genérica (entity, repository, service), utilitários, validadores, DTOs
147
+ ├── user/ # Módulo de gerenciamento de usuários (CRUD completo)
148
+ ├── app.module.ts # Módulo raiz da aplicação
149
+ ├── main.ts # Arquivo de entrada (bootstrap da aplicação)
150
+ └── data-source.ts# Configuração da conexão com o banco de dados para o TypeORM
151
+ ```
152
+
153
+ ---
154
+
155
+ ## 🔌 Addons Disponíveis
156
+
157
+ Na pasta `addons/` do repositório de templates, você encontra módulos opcionais que podem ser adicionados ao projeto:
158
+
159
+ | Addon | Descrição |
160
+ | ------------ | -------------------------------------------------------------------- |
161
+ | `.github` | Workflows de CI/CD, Dependabot, labeler, semantic PR, stale issues |
162
+ | `.husky` | Git hooks para Conventional Commits e lint pré-commit |
163
+ | `cloudinary` | Módulo NestJS para upload, delete e replace de imagens no Cloudinary |
164
+
165
+ ---
166
+
167
+ ## 🔧 Scripts Úteis
168
+
169
+ ### Migrations do TypeORM
170
+
171
+ - **Gerar uma nova migration a partir das mudanças nas entidades:**
172
+
173
+ ```bash
174
+ npm run migration:generate -- -n NomeDaMigration
175
+ ```
176
+
177
+ - **Executar migrations pendentes:**
178
+
179
+ ```bash
180
+ npm run migration:run
181
+ ```
182
+
183
+ - **Reverter a última migration:**
184
+ ```bash
185
+ npm run migration:revert
186
+ ```
187
+
188
+ ### Testes
189
+
190
+ - **Executar todos os testes unitários e de integração:**
191
+
192
+ ```bash
193
+ npm run test
194
+ ```
195
+
196
+ - **Executar testes em modo de observação:**
197
+
198
+ ```bash
199
+ npm run test:watch
200
+ ```
201
+
202
+ - **Verificar a cobertura de testes:**
203
+
204
+ ```bash
205
+ npm run test:cov
206
+ ```
207
+
208
+ - **Executar testes end-to-end (E2E):**
209
+ ```bash
210
+ npm run test:e2e
211
+ ```
212
+
213
+ ### Lint e Formatação
214
+
215
+ - **Verificar e corrigir erros de lint com ESLint:**
216
+
217
+ ```bash
218
+ npm run lint
219
+ ```
220
+
221
+ - **Formatar o código com Prettier:**
222
+ ```bash
223
+ npm run format
224
+ ```
@@ -0,0 +1,11 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "npm"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
7
+ groups:
8
+ dependencies:
9
+ patterns:
10
+ - "*"
11
+ open-pull-requests-limit: 10
@@ -0,0 +1,34 @@
1
+ # Area Labels
2
+ area/auth:
3
+ - src/auth/**/*
4
+ - src/common/guards/**/*
5
+ - src/common/decorators/**/*
6
+
7
+ area/user:
8
+ - src/user/**/*
9
+
10
+ area/project:
11
+ - src/project/**/*
12
+
13
+ area/news:
14
+ - src/news/**/*
15
+
16
+ area/event:
17
+ - src/event/**/*
18
+
19
+ # Type Labels (Inferred from files)
20
+ documentation:
21
+ - README.md
22
+ - LICENSE
23
+ - '**/*.md'
24
+
25
+ ci:
26
+ - .github/**/*
27
+
28
+ test:
29
+ - test/**/*
30
+ - '**/*.spec.ts'
31
+
32
+ dependencies:
33
+ - package.json
34
+ - package-lock.json
@@ -0,0 +1,24 @@
1
+ name: Check Branch Up-to-Date
2
+
3
+ on:
4
+ pull_request:
5
+ branches: [ main, develop, master, dev ]
6
+
7
+ jobs:
8
+ check-up-to-date:
9
+ name: Check if branch is up-to-date
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout code
13
+ uses: actions/checkout@v4
14
+ with:
15
+ fetch-depth: 0
16
+
17
+ - name: Check if branch is up-to-date
18
+ run: |
19
+ git fetch origin ${{ github.base_ref }}
20
+ git fetch origin ${{ github.head_ref }}
21
+ if ! git merge-base --is-ancestor origin/${{ github.base_ref }} origin/${{ github.head_ref }}; then
22
+ echo "::error::Branch is behind ${{ github.base_ref }}. Please merge/rebase before continuing."
23
+ exit 1
24
+ fi
@@ -0,0 +1,29 @@
1
+ name: CI
2
+ on:
3
+ push:
4
+ branches: [ main, develop, master, dev ]
5
+ pull_request:
6
+ branches: [ main, develop, master, dev ]
7
+
8
+ jobs:
9
+ build-and-test:
10
+ name: Build and Test
11
+ runs-on: ubuntu-latest
12
+
13
+ strategy:
14
+ matrix:
15
+ node-version: [24.x]
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+ - name: Setup Node.js ${{ matrix.node-version }}
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: ${{ matrix.node-version }}
23
+ - name: Install dependencies
24
+ run: npm install
25
+ - name: Lint
26
+ run: npm run lint
27
+
28
+ - name: Build
29
+ run: npm run build
@@ -0,0 +1,22 @@
1
+ name: Release Drafter
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ pull_request:
8
+ types: [opened, reopened, synchronize]
9
+
10
+ permissions:
11
+ contents: read
12
+
13
+ jobs:
14
+ update_release_draft:
15
+ permissions:
16
+ contents: write
17
+ pull-requests: write
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - uses: release-drafter/release-drafter@v6
21
+ env:
22
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,16 @@
1
+ name: "Pull Request Labeler"
2
+ on:
3
+ pull_request_target:
4
+ types: [opened, synchronize, reopened]
5
+
6
+ jobs:
7
+ triage:
8
+ permissions:
9
+ contents: read
10
+ pull-requests: write
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/labeler@v5
14
+ with:
15
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
16
+ sync-labels: true
@@ -0,0 +1,33 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*'
7
+
8
+ jobs:
9
+ release:
10
+ name: Create Release
11
+ runs-on: ubuntu-latest
12
+ permissions:
13
+ contents: write
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Setup Node.js
19
+ uses: actions/setup-node@v4
20
+ with:
21
+ node-version: '20.x'
22
+
23
+ - name: Install dependencies
24
+ run: npm install
25
+
26
+ - name: Build
27
+ run: npm run build
28
+
29
+ - name: Create Release
30
+ uses: softprops/action-gh-release@v1
31
+ if: startsWith(github.ref, 'refs/tags/')
32
+ with:
33
+ generate_release_notes: true
@@ -0,0 +1,17 @@
1
+ name: Security Audit
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, develop, master, dev ]
6
+ pull_request:
7
+ branches: [ main, develop, master, dev ]
8
+
9
+ jobs:
10
+ audit:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - name: Install dependencies
15
+ run: npm install
16
+ - name: Audit components
17
+ run: npm audit --audit-level=critical
@@ -0,0 +1,31 @@
1
+ name: Semantic PR
2
+
3
+ on:
4
+ pull_request:
5
+ types:
6
+ - opened
7
+ - edited
8
+ - synchronize
9
+
10
+ jobs:
11
+ main:
12
+ name: Validate PR title
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: amannn/action-semantic-pull-request@v5
16
+ env:
17
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18
+ with:
19
+ types: |
20
+ feat
21
+ fix
22
+ docs
23
+ style
24
+ refactor
25
+ perf
26
+ test
27
+ build
28
+ ci
29
+ chore
30
+ revert
31
+ requireScope: false
@@ -0,0 +1,24 @@
1
+ name: "Stale"
2
+ on:
3
+ schedule:
4
+ - cron: "30 1 */4 * *"
5
+
6
+ jobs:
7
+ stale:
8
+ runs-on: ubuntu-latest
9
+ permissions:
10
+ issues: write
11
+ pull-requests: write
12
+ steps:
13
+ - uses: actions/stale@v9
14
+ with:
15
+ stale-issue-message: "Esta issue está inativa há 60 dias. Marque como 'fresco' ou comente para reativar."
16
+ stale-pr-message: "Este PR está inativo há 60 dias. Marque como 'fresco' ou comente para reativar."
17
+ close-issue-message: "Esta issue foi fechada por inatividade."
18
+ close-pr-message: "Este PR foi fechado por inatividade."
19
+ days-before-issue-stale: 60
20
+ days-before-pr-stale: 60
21
+ days-before-issue-close: 7
22
+ days-before-pr-close: 7
23
+ exempt-issue-labels: "security,bug,enhancement,pinned,long-term"
24
+ exempt-pr-labels: "security,bug,enhancement,pinned,long-term"
@@ -0,0 +1,17 @@
1
+ #!/bin/sh
2
+
3
+ # Regex for Conventional Commits
4
+ pattern="^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))?: .+$"
5
+
6
+ while read -r line; do
7
+ if ! echo "$line" | grep -qE "$pattern"; then
8
+ echo "❌ Invalid commit message format."
9
+ echo "Please use the Conventional Commits pattern:"
10
+ echo " <type>(<scope>): <subject>"
11
+ echo "Valid types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert"
12
+ echo "Example: feat(auth): add google login"
13
+ exit 1
14
+ fi
15
+ # Only check the first line (subject)
16
+ break
17
+ done < "$1"
@@ -0,0 +1 @@
1
+ npm run lint
@@ -0,0 +1,17 @@
1
+ [
2
+ {
3
+ "name": "cloudinary",
4
+ "label": "Cloudinary (Upload de Imagens)",
5
+ "dest": "src/cloudinary"
6
+ },
7
+ {
8
+ "name": ".github",
9
+ "label": "GitHub Actions (CI/CD)",
10
+ "dest": ".github"
11
+ },
12
+ {
13
+ "name": ".husky",
14
+ "label": "Husky (Lint & Commits)",
15
+ "dest": ".husky"
16
+ }
17
+ ]
@@ -0,0 +1,11 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from '@nestjs/config';
3
+ import { CloudinaryProvider } from './cloudinary.provider';
4
+ import { CloudinaryService } from './cloudinary.service';
5
+
6
+ @Module({
7
+ imports: [ConfigModule],
8
+ providers: [CloudinaryProvider, CloudinaryService],
9
+ exports: [CloudinaryService],
10
+ })
11
+ export class CloudinaryModule {}
@@ -0,0 +1,16 @@
1
+ import { v2 as cloudinary } from 'cloudinary';
2
+ import { ConfigService } from '@nestjs/config';
3
+
4
+ export const CloudinaryProvider = {
5
+ provide: 'CLOUDINARY',
6
+ useFactory: (configService: ConfigService) => {
7
+ cloudinary.config({
8
+ cloud_name: configService.get<string>('CLOUDINARY_CLOUD_NAME'),
9
+ api_key: configService.get<string>('CLOUDINARY_API_KEY'),
10
+ api_secret: configService.get<string>('CLOUDINARY_API_SECRET'),
11
+ secure: true,
12
+ });
13
+ return cloudinary;
14
+ },
15
+ inject: [ConfigService],
16
+ };
@@ -0,0 +1,54 @@
1
+ import { Injectable, Inject, BadRequestException } from '@nestjs/common';
2
+ import { UploadApiResponse, v2 as cloudinaryType } from 'cloudinary';
3
+ import { ERRORS } from '../common/constants/errors.constants';
4
+
5
+ @Injectable()
6
+ export class CloudinaryService {
7
+ constructor(
8
+ @Inject('CLOUDINARY') private cloudinaryInstance: typeof cloudinaryType,
9
+ ) {}
10
+
11
+ async uploadImage(
12
+ file: Express.Multer.File,
13
+ folder: string,
14
+ ): Promise<UploadApiResponse> {
15
+ if (!file || !file.buffer) {
16
+ throw new BadRequestException(ERRORS.IMAGE.REQUIRED);
17
+ }
18
+
19
+ const fileBase64 = file.buffer.toString('base64');
20
+ const dataUri = `data:${file.mimetype};base64,${fileBase64}`;
21
+
22
+ return this.cloudinaryInstance.uploader.upload(dataUri, {
23
+ folder: folder,
24
+ resource_type: 'image',
25
+ });
26
+ }
27
+
28
+ async deleteImage(publicId: string): Promise<{ result: string }> {
29
+ return this.cloudinaryInstance.uploader.destroy(publicId) as Promise<{
30
+ result: string;
31
+ }>;
32
+ }
33
+
34
+ async replaceImage(
35
+ file: Express.Multer.File,
36
+ folder: string,
37
+ oldPublicId?: string,
38
+ ): Promise<UploadApiResponse> {
39
+ if (!file) {
40
+ throw new BadRequestException(ERRORS.IMAGE.REQUIRED);
41
+ }
42
+ if (oldPublicId) {
43
+ await this.deleteImage(oldPublicId);
44
+ }
45
+ return this.uploadImage(file, folder);
46
+ }
47
+
48
+ async deleteImages(publicIds: string[]): Promise<Record<string, unknown>> {
49
+ if (!publicIds.length) return {};
50
+ return this.cloudinaryInstance.api.delete_resources(publicIds) as Promise<
51
+ Record<string, unknown>
52
+ >;
53
+ }
54
+ }
@@ -0,0 +1,58 @@
1
+ version: "3.9"
2
+
3
+ services:
4
+ api-prod:
5
+ container_name: api_prod
6
+ build:
7
+ context: .
8
+ dockerfile: Dockerfile
9
+ target: production
10
+ command: npm run start:prod
11
+ ports:
12
+ - "3000:3000"
13
+ env_file:
14
+ - .env
15
+ depends_on:
16
+ postgres:
17
+ condition: service_healthy
18
+ restart: unless-stopped
19
+ profiles: ["prod"]
20
+
21
+ api-dev:
22
+ container_name: api_dev
23
+ build:
24
+ context: .
25
+ dockerfile: Dockerfile
26
+ target: development
27
+ command: npm run start:dev
28
+ ports:
29
+ - "3000:3000"
30
+ env_file:
31
+ - .env
32
+ depends_on:
33
+ postgres:
34
+ condition: service_healthy
35
+ volumes:
36
+ - .:/usr/src/app
37
+ - /usr/src/app/node_modules
38
+ restart: unless-stopped
39
+ profiles: ["dev"]
40
+
41
+ postgres:
42
+ image: postgres:15
43
+ container_name: postgres
44
+ restart: unless-stopped
45
+ healthcheck:
46
+ test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
47
+ interval: 10s
48
+ timeout: 5s
49
+ retries: 5
50
+ env_file:
51
+ - .env
52
+ ports:
53
+ - "5432:5432"
54
+ volumes:
55
+ - db_data:/var/lib/postgresql/data
56
+
57
+ volumes:
58
+ db_data:
@@ -0,0 +1,34 @@
1
+ // @ts-check
2
+ import eslint from '@eslint/js';
3
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
4
+ import globals from 'globals';
5
+ import tseslint from 'typescript-eslint';
6
+
7
+ export default tseslint.config(
8
+ {
9
+ ignores: ['eslint.config.mjs'],
10
+ },
11
+ eslint.configs.recommended,
12
+ ...tseslint.configs.recommendedTypeChecked,
13
+ eslintPluginPrettierRecommended,
14
+ {
15
+ languageOptions: {
16
+ globals: {
17
+ ...globals.node,
18
+ ...globals.jest,
19
+ },
20
+ sourceType: 'commonjs',
21
+ parserOptions: {
22
+ projectService: true,
23
+ tsconfigRootDir: import.meta.dirname,
24
+ },
25
+ },
26
+ },
27
+ {
28
+ rules: {
29
+ '@typescript-eslint/no-explicit-any': 'off',
30
+ '@typescript-eslint/no-floating-promises': 'warn',
31
+ '@typescript-eslint/no-unsafe-argument': 'warn'
32
+ },
33
+ },
34
+ );