innovationhub-cli 1.0.1 → 2.0.0
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.
- package/LICENSE +21 -0
- package/README.md +148 -86
- package/index.js +225 -47
- package/package.json +39 -31
- package/templates/nest/.env.example +41 -0
- package/templates/nest/.prettierrc +4 -0
- package/templates/nest/Dockerfile +17 -0
- package/templates/nest/README.md +224 -0
- package/templates/nest/addons/.github/dependabot.yml +11 -0
- package/templates/nest/addons/.github/labeler.yml +34 -0
- package/templates/nest/addons/.github/workflows/check-branch.yml +24 -0
- package/templates/nest/addons/.github/workflows/ci.yml +29 -0
- package/templates/nest/addons/.github/workflows/draft-release.yml +22 -0
- package/templates/nest/addons/.github/workflows/pr-labeler.yml +16 -0
- package/templates/nest/addons/.github/workflows/release.yml +33 -0
- package/templates/nest/addons/.github/workflows/security-audit.yml +17 -0
- package/templates/nest/addons/.github/workflows/semantic-pr.yml +31 -0
- package/templates/nest/addons/.github/workflows/stale.yml +24 -0
- package/templates/nest/addons/.husky/commit-msg +17 -0
- package/templates/nest/addons/.husky/pre-commit +1 -0
- package/templates/nest/addons/addons.json +17 -0
- package/templates/nest/addons/cloudinary/cloudinary.module.ts +11 -0
- package/templates/nest/addons/cloudinary/cloudinary.provider.ts +16 -0
- package/templates/nest/addons/cloudinary/cloudinary.service.ts +54 -0
- package/templates/nest/docker-compose.yml +58 -0
- package/templates/nest/eslint.config.mjs +34 -0
- package/templates/nest/jest.config.js +17 -0
- package/templates/nest/nest-cli.json +12 -0
- package/templates/nest/package.json +99 -0
- package/templates/nest/src/app.controller.ts +7 -0
- package/templates/nest/src/app.module.ts +69 -0
- package/templates/nest/src/app.service.ts +4 -0
- package/templates/nest/src/auth/auth.controller.ts +97 -0
- package/templates/nest/src/auth/auth.module.ts +46 -0
- package/templates/nest/src/auth/auth.service.ts +231 -0
- package/templates/nest/src/auth/decorators/roles.decorator.ts +5 -0
- package/templates/nest/src/auth/dto/change-password.dto.ts +21 -0
- package/templates/nest/src/auth/dto/login-response.dto.ts +25 -0
- package/templates/nest/src/auth/dto/login.dto.ts +15 -0
- package/templates/nest/src/auth/dto/refresh-token.dto.ts +12 -0
- package/templates/nest/src/auth/entities/refresh-token.entity.ts +18 -0
- package/templates/nest/src/auth/enums/role.enum.ts +4 -0
- package/templates/nest/src/auth/guards/jwt-auth.guard.ts +5 -0
- package/templates/nest/src/auth/guards/refresh-token.guard.ts +5 -0
- package/templates/nest/src/auth/guards/roles.guard.ts +23 -0
- package/templates/nest/src/auth/interfaces/jwt-payload.interface.ts +10 -0
- package/templates/nest/src/auth/strategies/jwt.strategy.ts +28 -0
- package/templates/nest/src/auth/strategies/local.strategy.ts +23 -0
- package/templates/nest/src/auth/strategies/refresh-token.strategy.ts +32 -0
- package/templates/nest/src/common/base.entity.ts +19 -0
- package/templates/nest/src/common/base.repository.ts +79 -0
- package/templates/nest/src/common/base.service.ts +28 -0
- package/templates/nest/src/common/constants/errors.constants.ts +33 -0
- package/templates/nest/src/common/decorators/user.decorator.ts +9 -0
- package/templates/nest/src/common/dto/base-query.dto.ts +56 -0
- package/templates/nest/src/common/irepository.ts +18 -0
- package/templates/nest/src/common/utils/duration.utils.ts +33 -0
- package/templates/nest/src/common/utils/pagination.utils.ts +35 -0
- package/templates/nest/src/common/utils/slug.utils.ts +14 -0
- package/templates/nest/src/common/utils/transform.utils.ts +62 -0
- package/templates/nest/src/common/validators/is-date-after.validator.ts +40 -0
- package/templates/nest/src/data-source.ts +23 -0
- package/templates/nest/src/main.ts +44 -0
- package/templates/nest/src/user/dto/create-user.dto.ts +50 -0
- package/templates/nest/src/user/dto/query-users.dto.ts +23 -0
- package/templates/nest/src/user/dto/update-user.dto.ts +15 -0
- package/templates/nest/src/user/entities/user.entity.ts +66 -0
- package/templates/nest/src/user/user.controller.ts +172 -0
- package/templates/nest/src/user/user.module.ts +15 -0
- package/templates/nest/src/user/user.repository.ts +61 -0
- package/templates/nest/src/user/user.service.ts +138 -0
- package/templates/nest/template.json +5 -0
- package/templates/nest/test/jest-e2e.json +12 -0
- package/templates/nest/tsconfig.build.json +4 -0
- package/templates/nest/tsconfig.json +25 -0
- package/templates/python/.env.example +37 -0
- package/templates/python/Dockerfile +18 -0
- package/templates/python/README.md +219 -0
- package/templates/python/addons/.github/dependabot.yml +11 -0
- package/templates/python/addons/.github/labeler.yml +29 -0
- package/templates/python/addons/.github/workflows/check-branch.yml +24 -0
- package/templates/python/addons/.github/workflows/ci.yml +30 -0
- package/templates/python/addons/.github/workflows/draft-release.yml +22 -0
- package/templates/python/addons/.github/workflows/pr-labeler.yml +16 -0
- package/templates/python/addons/.github/workflows/release.yml +30 -0
- package/templates/python/addons/.github/workflows/security-audit.yml +21 -0
- package/templates/python/addons/.github/workflows/semantic-pr.yml +31 -0
- package/templates/python/addons/.github/workflows/stale.yml +24 -0
- package/templates/python/addons/addons.json +17 -0
- package/templates/python/addons/cloudinary/service.py +67 -0
- package/templates/python/addons/pre-commit/.pre-commit-config.yaml +31 -0
- package/templates/python/alembic/env.py +56 -0
- package/templates/python/alembic/script.py.mako +26 -0
- package/templates/python/alembic/versions/.gitkeep +0 -0
- package/templates/python/alembic.ini +39 -0
- package/templates/python/app/__init__.py +0 -0
- package/templates/python/app/auth/__init__.py +5 -0
- package/templates/python/app/auth/dependencies.py +118 -0
- package/templates/python/app/auth/enums.py +6 -0
- package/templates/python/app/auth/models.py +18 -0
- package/templates/python/app/auth/router.py +68 -0
- package/templates/python/app/auth/schemas.py +58 -0
- package/templates/python/app/auth/service.py +180 -0
- package/templates/python/app/common/__init__.py +18 -0
- package/templates/python/app/common/base_model.py +26 -0
- package/templates/python/app/common/base_repository.py +83 -0
- package/templates/python/app/common/errors.py +35 -0
- package/templates/python/app/common/pagination.py +22 -0
- package/templates/python/app/common/schemas.py +20 -0
- package/templates/python/app/common/utils.py +15 -0
- package/templates/python/app/core/__init__.py +4 -0
- package/templates/python/app/core/config.py +55 -0
- package/templates/python/app/core/database.py +20 -0
- package/templates/python/app/main.py +33 -0
- package/templates/python/app/user/__init__.py +4 -0
- package/templates/python/app/user/models.py +26 -0
- package/templates/python/app/user/repository.py +84 -0
- package/templates/python/app/user/router.py +170 -0
- package/templates/python/app/user/schemas.py +60 -0
- package/templates/python/app/user/service.py +114 -0
- package/templates/python/docker-compose.yml +55 -0
- package/templates/python/pyproject.toml +46 -0
- package/templates/python/requirements-dev.txt +7 -0
- package/templates/python/requirements.txt +20 -0
- package/templates/python/template.json +5 -0
- package/utils/template.js +165 -0
- package/utils/git.js +0 -47
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Liga Academica de Empreededorismo Innovation Hub
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,86 +1,148 @@
|
|
|
1
|
-
# InnovationHub CLI
|
|
2
|
-
|
|
3
|
-
Ferramenta oficial para inicializar projetos Backend
|
|
4
|
-
|
|
5
|
-
## Instalação
|
|
6
|
-
|
|
7
|
-
Para usar sem instalar (recomendado):
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
npx innovationhub-cli
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
Para instalar globalmente:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npm install -g innovationhub-cli
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
## Como Usar
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
1
|
+
# InnovationHub CLI
|
|
2
|
+
|
|
3
|
+
Ferramenta oficial para inicializar projetos Backend na InnovationHub.
|
|
4
|
+
|
|
5
|
+
## Instalação
|
|
6
|
+
|
|
7
|
+
Para usar sem instalar (recomendado):
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx innovationhub-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Para instalar globalmente:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g innovationhub-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Como Usar
|
|
20
|
+
|
|
21
|
+
### Modo Interativo
|
|
22
|
+
|
|
23
|
+
Execute o comando e siga os passos:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
innovationhub
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
O CLI vai guiar você por:
|
|
30
|
+
|
|
31
|
+
1. **Nome do Projeto** — nome da pasta
|
|
32
|
+
2. **Stack** — NestJS ou Python (FastAPI)
|
|
33
|
+
3. **Addons** — recursos opcionais (variam por stack)
|
|
34
|
+
4. **Resumo** — revise e confirme
|
|
35
|
+
5. **Dependências** — instalar automaticamente (opcional)
|
|
36
|
+
|
|
37
|
+
### Modo Direto (CLI Flags)
|
|
38
|
+
|
|
39
|
+
Para automação ou uso rápido via flags:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Criar projeto completo
|
|
43
|
+
innovationhub --name meu-api --stack nest --addons cloudinary,.github --install
|
|
44
|
+
|
|
45
|
+
# Mínimo, sem addons e sem confirmações
|
|
46
|
+
innovationhub -n meu-api -s nest -y
|
|
47
|
+
|
|
48
|
+
# Python com todos os addons
|
|
49
|
+
innovationhub -n minha-api -s python -a cloudinary,.github,pre-commit -i -y
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
#### Flags Disponíveis
|
|
53
|
+
|
|
54
|
+
| Flag | Short | Descrição |
|
|
55
|
+
| ------------------ | ----- | ------------------------------------- |
|
|
56
|
+
| `--name <nome>` | `-n` | Nome do projeto |
|
|
57
|
+
| `--stack <stack>` | `-s` | Stack (`nest` ou `python`) |
|
|
58
|
+
| `--addons <lista>` | `-a` | Addons separados por vírgula |
|
|
59
|
+
| `--install` | `-i` | Instalar dependências automaticamente |
|
|
60
|
+
| `--yes` | `-y` | Pular confirmações |
|
|
61
|
+
| `--version` | `-v` | Mostrar versão |
|
|
62
|
+
| `--help` | `-h` | Mostrar ajuda |
|
|
63
|
+
|
|
64
|
+
> **Dica:** as flags são opcionais — se faltar alguma, o CLI pergunta interativamente.
|
|
65
|
+
|
|
66
|
+
## Stacks Disponíveis
|
|
67
|
+
|
|
68
|
+
| Stack | Descrição |
|
|
69
|
+
| -------------------- | ------------------------------------------------- |
|
|
70
|
+
| **NestJS** | Backend Node.js com TypeScript, TypeORM, JWT Auth |
|
|
71
|
+
| **Python (FastAPI)** | Backend Python com SQLAlchemy, Alembic, JWT Auth |
|
|
72
|
+
|
|
73
|
+
### Criando Novas Stacks
|
|
74
|
+
|
|
75
|
+
Para adicionar uma nova stack, crie uma pasta em `templates/{nome}/` com um `template.json`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"label": "Nome Exibido",
|
|
80
|
+
"description": "Descrição curta da stack"
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
O CLI descobre as stacks automaticamente — sem precisar alterar o código.
|
|
85
|
+
|
|
86
|
+
## Addons por Stack
|
|
87
|
+
|
|
88
|
+
Cada stack possui addons específicos. Ao selecionar uma stack, o CLI mostra apenas os addons disponíveis para ela.
|
|
89
|
+
|
|
90
|
+
**NestJS:**
|
|
91
|
+
|
|
92
|
+
- Cloudinary (Upload de Imagens)
|
|
93
|
+
- GitHub Actions (CI/CD)
|
|
94
|
+
- Husky (Lint & Commits)
|
|
95
|
+
|
|
96
|
+
**Python (FastAPI):**
|
|
97
|
+
|
|
98
|
+
- Cloudinary (Upload de Imagens)
|
|
99
|
+
- GitHub Actions (CI/CD)
|
|
100
|
+
- Pre-commit (Lint & Formatação)
|
|
101
|
+
|
|
102
|
+
### Criando Novos Addons
|
|
103
|
+
|
|
104
|
+
Para adicionar um novo addon a uma stack:
|
|
105
|
+
|
|
106
|
+
1. Crie uma pasta em `templates/{stack}/addons/{nome-do-addon}/`
|
|
107
|
+
2. Adicione a entrada no `templates/{stack}/addons/addons.json`:
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"name": "nome-do-addon",
|
|
111
|
+
"label": "Nome Amigável",
|
|
112
|
+
"dest": "caminho/destino"
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
O CLI descobre os addons automaticamente — sem precisar alterar o código.
|
|
117
|
+
|
|
118
|
+
## Desenvolvimento
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Clone este repositório
|
|
122
|
+
git clone https://github.com/ProHub-Innovation/innovationhub-cli.git
|
|
123
|
+
cd innovationhub-cli
|
|
124
|
+
|
|
125
|
+
# Instale as dependências
|
|
126
|
+
npm install
|
|
127
|
+
|
|
128
|
+
# Link globalmente para testar
|
|
129
|
+
npm link
|
|
130
|
+
|
|
131
|
+
# Rode o comando
|
|
132
|
+
innovationhub
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Publicação
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# Atualizar versão (semver)
|
|
139
|
+
npm version patch|minor|major
|
|
140
|
+
|
|
141
|
+
# Login no NPM (primeira vez)
|
|
142
|
+
npm login
|
|
143
|
+
|
|
144
|
+
# Publicar
|
|
145
|
+
npm publish --access public
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Os usuários que usam `npx innovationhub-cli` pegarão a nova versão automaticamente.
|
package/index.js
CHANGED
|
@@ -1,67 +1,245 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import * as p from
|
|
3
|
-
import
|
|
2
|
+
import * as p from "@clack/prompts";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import fs from "node:fs/promises";
|
|
5
|
+
import { createRequire } from "node:module";
|
|
6
|
+
import { parseArgs } from "node:util";
|
|
7
|
+
import {
|
|
8
|
+
getAvailableStacks,
|
|
9
|
+
getAvailableAddons,
|
|
10
|
+
setupProject,
|
|
11
|
+
installDependencies,
|
|
12
|
+
} from "./utils/template.js";
|
|
13
|
+
|
|
14
|
+
const require = createRequire(import.meta.url);
|
|
15
|
+
const { version } = require("./package.json");
|
|
16
|
+
|
|
17
|
+
// ── Parse CLI flags ──────────────────────────────────────────────
|
|
18
|
+
const { values: flags } = parseArgs({
|
|
19
|
+
options: {
|
|
20
|
+
name: { type: "string", short: "n" },
|
|
21
|
+
stack: { type: "string", short: "s" },
|
|
22
|
+
addons: { type: "string", short: "a" },
|
|
23
|
+
install: { type: "boolean", short: "i", default: false },
|
|
24
|
+
yes: { type: "boolean", short: "y", default: false },
|
|
25
|
+
help: { type: "boolean", short: "h", default: false },
|
|
26
|
+
version: { type: "boolean", short: "v", default: false },
|
|
27
|
+
},
|
|
28
|
+
strict: false,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
if (flags.version) {
|
|
32
|
+
console.log(`innovationhub-cli v${version}`);
|
|
33
|
+
process.exit(0);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (flags.help) {
|
|
37
|
+
console.log(`
|
|
38
|
+
${pc.bgCyan(pc.black(" InnovationHub CLI "))} v${version}
|
|
39
|
+
|
|
40
|
+
${pc.bold("Uso:")}
|
|
41
|
+
innovationhub [opções]
|
|
42
|
+
|
|
43
|
+
${pc.bold("Opções:")}
|
|
44
|
+
-n, --name <nome> Nome do projeto
|
|
45
|
+
-s, --stack <stack> Stack do backend
|
|
46
|
+
-a, --addons <addons> Addons separados por vírgula
|
|
47
|
+
-i, --install Instalar dependências automaticamente
|
|
48
|
+
-y, --yes Pular confirmação
|
|
49
|
+
-v, --version Mostrar versão
|
|
50
|
+
-h, --help Mostrar ajuda
|
|
51
|
+
|
|
52
|
+
${pc.bold("Exemplos:")}
|
|
53
|
+
${pc.dim("# Modo interativo")}
|
|
54
|
+
innovationhub
|
|
55
|
+
|
|
56
|
+
${pc.dim("# Modo direto")}
|
|
57
|
+
innovationhub --name meu-api --stack nest --addons cloudinary,.github --install
|
|
58
|
+
|
|
59
|
+
${pc.dim("# Mínimo (sem addons)")}
|
|
60
|
+
innovationhub -n meu-api -s nest -y
|
|
61
|
+
`);
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
4
64
|
|
|
5
65
|
async function main() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
66
|
+
p.intro(pc.bgCyan(pc.black(` InnovationHub CLI v${version} `)));
|
|
67
|
+
|
|
68
|
+
// Descobrir stacks disponíveis
|
|
69
|
+
const availableStacks = await getAvailableStacks();
|
|
70
|
+
if (availableStacks.length === 0) {
|
|
71
|
+
p.cancel("Nenhum template encontrado em templates/.");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const validStackNames = availableStacks.map((s) => s.value);
|
|
76
|
+
|
|
77
|
+
// 1. Nome do projeto
|
|
78
|
+
let projectName = flags.name;
|
|
79
|
+
if (!projectName) {
|
|
80
|
+
projectName = await p.text({
|
|
81
|
+
message: "Qual o nome do seu projeto?",
|
|
82
|
+
placeholder: "meu-projeto",
|
|
83
|
+
validate: (value) => {
|
|
84
|
+
if (!value) return "Por favor, insira um nome.";
|
|
85
|
+
if (/[^a-z0-9-]/.test(value))
|
|
86
|
+
return "Use apenas letras minúsculas, números e hífens.";
|
|
87
|
+
},
|
|
15
88
|
});
|
|
16
89
|
|
|
17
90
|
if (p.isCancel(projectName)) {
|
|
18
|
-
|
|
91
|
+
p.cancel("Operação cancelada.");
|
|
92
|
+
process.exit(0);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 2. Verificar se a pasta já existe
|
|
97
|
+
try {
|
|
98
|
+
await fs.access(projectName);
|
|
99
|
+
if (flags.yes) {
|
|
100
|
+
await fs.rm(projectName, { recursive: true, force: true });
|
|
101
|
+
} else {
|
|
102
|
+
const overwrite = await p.confirm({
|
|
103
|
+
message: `A pasta '${projectName}' já existe. Deseja sobrescrever?`,
|
|
104
|
+
initialValue: false,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
if (p.isCancel(overwrite) || !overwrite) {
|
|
108
|
+
p.cancel("Operação cancelada.");
|
|
19
109
|
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
await fs.rm(projectName, { recursive: true, force: true });
|
|
20
113
|
}
|
|
114
|
+
} catch {
|
|
115
|
+
// Pasta não existe, seguir normalmente
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 3. Escolher stack
|
|
119
|
+
let stack = flags.stack;
|
|
120
|
+
if (stack && !validStackNames.includes(stack)) {
|
|
121
|
+
p.cancel(
|
|
122
|
+
`Stack '${stack}' inválida. Disponíveis: ${validStackNames.join(", ")}`,
|
|
123
|
+
);
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
21
126
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{ value: 'front', label: 'Frontend (Repositório de Interface)' },
|
|
27
|
-
],
|
|
127
|
+
if (!stack) {
|
|
128
|
+
stack = await p.select({
|
|
129
|
+
message: "Qual a stack do Backend?",
|
|
130
|
+
options: availableStacks,
|
|
28
131
|
});
|
|
29
132
|
|
|
30
|
-
if (p.isCancel(
|
|
31
|
-
|
|
32
|
-
|
|
133
|
+
if (p.isCancel(stack)) {
|
|
134
|
+
p.cancel("Operação cancelada.");
|
|
135
|
+
process.exit(0);
|
|
33
136
|
}
|
|
137
|
+
}
|
|
34
138
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
message: 'Qual a stack do Frontend?',
|
|
49
|
-
options: [
|
|
50
|
-
{ value: 'next', label: 'Next.js' },
|
|
51
|
-
{ value: 'vue', label: 'Vue.js' },
|
|
52
|
-
{ value: 'angular', label: 'Angular' },
|
|
53
|
-
],
|
|
54
|
-
});
|
|
139
|
+
// 4. Ler addons disponíveis para a stack escolhida
|
|
140
|
+
const availableAddons = await getAvailableAddons(stack);
|
|
141
|
+
let selectedAddons = [];
|
|
142
|
+
|
|
143
|
+
if (flags.addons) {
|
|
144
|
+
selectedAddons = flags.addons.split(",").map((a) => a.trim());
|
|
145
|
+
const validNames = availableAddons.map((a) => a.name);
|
|
146
|
+
const invalid = selectedAddons.filter((a) => !validNames.includes(a));
|
|
147
|
+
if (invalid.length > 0) {
|
|
148
|
+
p.cancel(
|
|
149
|
+
`Addon(s) inválido(s): ${invalid.join(", ")}\nDisponíveis: ${validNames.join(", ")}`,
|
|
150
|
+
);
|
|
151
|
+
process.exit(1);
|
|
55
152
|
}
|
|
153
|
+
} else if (availableAddons.length > 0) {
|
|
154
|
+
const addonOptions = [
|
|
155
|
+
{ value: "none", label: "Nenhum", hint: "pule esta etapa" },
|
|
156
|
+
...availableAddons.map((a) => ({ value: a.name, label: a.label })),
|
|
157
|
+
];
|
|
56
158
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
159
|
+
const addonsRaw = await p.multiselect({
|
|
160
|
+
message: "Selecione os recursos opcionais:",
|
|
161
|
+
options: addonOptions,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (p.isCancel(addonsRaw)) {
|
|
165
|
+
p.cancel("Operação cancelada.");
|
|
166
|
+
process.exit(0);
|
|
60
167
|
}
|
|
61
168
|
|
|
62
|
-
|
|
169
|
+
selectedAddons = addonsRaw.filter((a) => a !== "none");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// 5. Resumo antes de executar
|
|
173
|
+
const stackMeta = availableStacks.find((s) => s.value === stack);
|
|
174
|
+
const stackLabel = stackMeta?.label || stack;
|
|
175
|
+
const addonsLabel =
|
|
176
|
+
selectedAddons.length > 0
|
|
177
|
+
? selectedAddons
|
|
178
|
+
.map(
|
|
179
|
+
(name) =>
|
|
180
|
+
availableAddons.find((a) => a.name === name)?.label ?? name,
|
|
181
|
+
)
|
|
182
|
+
.join(", ")
|
|
183
|
+
: "Nenhum";
|
|
184
|
+
|
|
185
|
+
p.note(
|
|
186
|
+
[
|
|
187
|
+
`Projeto: ${pc.cyan(projectName)}`,
|
|
188
|
+
`Stack: ${pc.cyan(stackLabel)}`,
|
|
189
|
+
`Addons: ${pc.cyan(addonsLabel)}`,
|
|
190
|
+
].join("\n"),
|
|
191
|
+
"Resumo",
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
if (!flags.yes) {
|
|
195
|
+
const confirmed = await p.confirm({
|
|
196
|
+
message: "Confirma a criação do projeto?",
|
|
197
|
+
initialValue: true,
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
if (p.isCancel(confirmed) || !confirmed) {
|
|
201
|
+
p.cancel("Operação cancelada.");
|
|
202
|
+
process.exit(0);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// 6. Criar projeto
|
|
207
|
+
await setupProject(stack, projectName, selectedAddons);
|
|
208
|
+
|
|
209
|
+
// 7. Instalar dependências
|
|
210
|
+
const installCmd = stackMeta?.installCmd || "";
|
|
211
|
+
let installed = false;
|
|
212
|
+
|
|
213
|
+
if (installCmd && flags.install) {
|
|
214
|
+
await installDependencies(projectName, installCmd);
|
|
215
|
+
installed = true;
|
|
216
|
+
} else if (installCmd && !flags.yes) {
|
|
217
|
+
const shouldInstall = await p.confirm({
|
|
218
|
+
message: "Deseja instalar as dependências agora?",
|
|
219
|
+
initialValue: true,
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
if (!p.isCancel(shouldInstall) && shouldInstall) {
|
|
223
|
+
await installDependencies(projectName, installCmd);
|
|
224
|
+
installed = true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// 8. Próximos passos
|
|
229
|
+
const steps = [`1. cd ${projectName}`];
|
|
230
|
+
|
|
231
|
+
if (!installed && installCmd) {
|
|
232
|
+
steps.push(`2. ${installCmd}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
steps.push(
|
|
236
|
+
`${steps.length + 1}. Preencha as variáveis no arquivo .env`,
|
|
237
|
+
`${steps.length + 2}. docker compose up -d ${pc.dim("# subir banco de dados")}`,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
p.note(steps.join("\n"), "Próximos passos");
|
|
63
241
|
|
|
64
|
-
|
|
242
|
+
p.outro(pc.green("Projeto criado com sucesso!"));
|
|
65
243
|
}
|
|
66
244
|
|
|
67
|
-
main().catch(console.error);
|
|
245
|
+
main().catch(console.error);
|
package/package.json
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "innovationhub-cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "CLI oficial da InnovationHub para inicializar projetos
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"bin": {
|
|
7
|
-
"innovationhub": "index.js"
|
|
8
|
-
},
|
|
9
|
-
"repository": {
|
|
10
|
-
"type": "git",
|
|
11
|
-
"url": "git+https://github.com/
|
|
12
|
-
},
|
|
13
|
-
"scripts": {
|
|
14
|
-
"test": "echo \"Error: no test specified\" && exit 1"
|
|
15
|
-
},
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "innovationhub-cli",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "CLI oficial da InnovationHub para inicializar projetos.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"innovationhub": "index.js"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/ProHub-Innovation/innovationhub-cli.git"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"index.js",
|
|
18
|
+
"utils/",
|
|
19
|
+
"templates/",
|
|
20
|
+
"!templates/*/node_modules",
|
|
21
|
+
"!templates/*/dist",
|
|
22
|
+
"!templates/*/.ruff_cache",
|
|
23
|
+
"!templates/*/*.egg-info",
|
|
24
|
+
"!templates/*/package-lock.json"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"cli",
|
|
28
|
+
"scaffold",
|
|
29
|
+
"innovation-hub",
|
|
30
|
+
"backend"
|
|
31
|
+
],
|
|
32
|
+
"author": "",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"type": "module",
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"@clack/prompts": "^1.0.1",
|
|
37
|
+
"picocolors": "^1.1.1"
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Configurações do Postgres - Docker (OBRIGATÓRIAS)
|
|
2
|
+
POSTGRES_USER=postgres
|
|
3
|
+
POSTGRES_PASSWORD=docker
|
|
4
|
+
POSTGRES_DB=innovationhub
|
|
5
|
+
|
|
6
|
+
# Configurações do Banco de Dados
|
|
7
|
+
DATABASE_TYPE=postgres
|
|
8
|
+
DATABASE_HOST=postgres
|
|
9
|
+
DATABASE_PORT=5432
|
|
10
|
+
DATABASE_USERNAME=postgres
|
|
11
|
+
DATABASE_PASSWORD=docker
|
|
12
|
+
DATABASE_NAME=innovationhub
|
|
13
|
+
|
|
14
|
+
# Configurações JWT
|
|
15
|
+
JWT_SECRET=codigo-longo-aqui
|
|
16
|
+
JWT_EXPIRATION_TIME=15m # 15 minutos
|
|
17
|
+
JWT_REFRESH_SECRET=outro-codigo-longo-aqui
|
|
18
|
+
JWT_REFRESH_EXPIRATION_TIME=7d # 7 dias
|
|
19
|
+
|
|
20
|
+
# Senha padrão para novos usuários criados pelo admin ou para reset de senha
|
|
21
|
+
DEFAULT_PASSWORD=ih123 #Sua senha
|
|
22
|
+
|
|
23
|
+
# variavel de ambiente para configuração do CORS
|
|
24
|
+
CORS_ORIGIN=http://localhost:3001
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
# Configurações do Cloudinary
|
|
28
|
+
CLOUDINARY_CLOUD_NAME=####SEU_NOME_DE_NUVEM_DO_CLOUDINARY####
|
|
29
|
+
CLOUDINARY_API_KEY=####SUA_CHAVE_DE_API_DO_CLOUDINARY####
|
|
30
|
+
CLOUDINARY_API_SECRET=####SUA_CHAVE_SECRETA_DO_CLOUDINARY####
|
|
31
|
+
|
|
32
|
+
# Serviço de email
|
|
33
|
+
MAIL_HOST=smtp.gmail.com
|
|
34
|
+
MAIL_PORT=587
|
|
35
|
+
MAIL_USER=noreply@innovationhub.com
|
|
36
|
+
MAIL_PASSWORD=#xxxx_xxxx_xxxx_xxxx
|
|
37
|
+
MAIL_DESTINATION=innovationhub@gmail.com
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
EMAILDETECTIVE_API_KEY=sua_chave_api_aqui
|