nestforge-generator 0.2.0 → 0.3.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/README.md +11 -6
- package/README.pt-BR.md +11 -6
- package/dist/features/database.js +35 -0
- package/dist/features/database.js.map +1 -1
- package/dist/generator.js +7 -1
- package/dist/generator.js.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/prompts.js +3 -1
- package/dist/prompts.js.map +1 -1
- package/package.json +2 -1
- package/templates/drizzle/README.md +2 -0
- package/templates/drizzle/README.pt-BR.md +2 -0
- package/templates/prisma/.github/workflows/ci.yml +24 -1
- package/templates/prisma/ARCHITECTURE.md +7 -1
- package/templates/prisma/ARCHITECTURE.pt-BR.md +7 -1
- package/templates/prisma/README.md +11 -7
- package/templates/prisma/README.pt-BR.md +11 -7
- package/templates/prisma/ROADMAP.md +5 -1
- package/templates/prisma/ROADMAP.pt-BR.md +5 -1
- package/templates/prisma/TESTING.md +25 -3
- package/templates/prisma/TESTING.pt-BR.md +25 -3
- package/templates/prisma/docker-compose.yml +29 -1
- package/templates/prisma/docs/adding-a-module.md +246 -230
- package/templates/prisma/docs/features-markers.md +11 -1
- package/templates/prisma/prisma/schema.prisma +4 -0
- package/templates/prisma/src/auth/token.service.ts +12 -3
- package/templates/prisma/src/health/indicators/prisma-health.indicator.spec.ts +39 -22
- package/templates/prisma/src/health/indicators/prisma-health.indicator.ts +24 -19
- package/templates/typeorm/README.md +2 -0
- package/templates/typeorm/README.pt-BR.md +2 -0
|
@@ -8,7 +8,7 @@ This guide validates a project generated from the NestForge Prisma template.
|
|
|
8
8
|
|
|
9
9
|
* Node.js 20 or later
|
|
10
10
|
* npm 10 or later
|
|
11
|
-
* Docker when testing PostgreSQL, MySQL, Redis, or Mailpit
|
|
11
|
+
* Docker when testing PostgreSQL, MySQL, MongoDB, Redis, or Mailpit
|
|
12
12
|
|
|
13
13
|
SQLite can be tested without Docker.
|
|
14
14
|
|
|
@@ -30,10 +30,18 @@ npm run prisma:generate
|
|
|
30
30
|
|
|
31
31
|
## Apply the development schema
|
|
32
32
|
|
|
33
|
+
For PostgreSQL, MySQL, or SQLite:
|
|
34
|
+
|
|
33
35
|
```bash
|
|
34
36
|
npm run prisma:migrate -- --name init
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
For MongoDB:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run prisma:push
|
|
43
|
+
```
|
|
44
|
+
|
|
37
45
|
Run the seed when the generated project includes password authentication:
|
|
38
46
|
|
|
39
47
|
```bash
|
|
@@ -67,7 +75,7 @@ Unit tests mock Prisma and Redis, so they do not require real services.
|
|
|
67
75
|
npm run test:e2e
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
The `pretest:e2e` script runs `prisma migrate deploy` with `.env.test` before the suite starts.
|
|
78
|
+
The `pretest:e2e` script runs `prisma migrate deploy` for relational databases or `prisma db push` for MongoDB with `.env.test` before the suite starts.
|
|
71
79
|
|
|
72
80
|
Depending on the generated authentication strategy, the suite may cover:
|
|
73
81
|
|
|
@@ -110,11 +118,25 @@ npm test
|
|
|
110
118
|
npm run test:e2e
|
|
111
119
|
```
|
|
112
120
|
|
|
121
|
+
### MongoDB
|
|
122
|
+
|
|
123
|
+
MongoDB must run as a replica set because Prisma uses transactions for nested writes. The generated Docker Compose configures a single-node replica set:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
docker compose up -d mongodb
|
|
127
|
+
npm run prisma:push
|
|
128
|
+
npm run build
|
|
129
|
+
npm test
|
|
130
|
+
npm run test:e2e
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use different database names in `.env` and `.env.test`, such as `nestforge` and `nestforge_test`.
|
|
134
|
+
|
|
113
135
|
## Final checklist
|
|
114
136
|
|
|
115
137
|
* [ ] Dependencies install successfully
|
|
116
138
|
* [ ] Prisma Client is generated
|
|
117
|
-
* [ ] Migrations are applied
|
|
139
|
+
* [ ] Migrations are applied, or the MongoDB schema is pushed
|
|
118
140
|
* [ ] Seed runs when applicable
|
|
119
141
|
* [ ] Build passes
|
|
120
142
|
* [ ] Lint passes
|
|
@@ -8,7 +8,7 @@ Este guia valida um projeto gerado a partir do template Prisma do NestForge.
|
|
|
8
8
|
|
|
9
9
|
* Node.js 20 ou superior
|
|
10
10
|
* npm 10 ou superior
|
|
11
|
-
* Docker para testar PostgreSQL, MySQL, Redis ou Mailpit
|
|
11
|
+
* Docker para testar PostgreSQL, MySQL, MongoDB, Redis ou Mailpit
|
|
12
12
|
|
|
13
13
|
SQLite pode ser testado sem Docker.
|
|
14
14
|
|
|
@@ -30,10 +30,18 @@ npm run prisma:generate
|
|
|
30
30
|
|
|
31
31
|
## Aplicar o schema de desenvolvimento
|
|
32
32
|
|
|
33
|
+
Para PostgreSQL, MySQL ou SQLite:
|
|
34
|
+
|
|
33
35
|
```bash
|
|
34
36
|
npm run prisma:migrate -- --name init
|
|
35
37
|
```
|
|
36
38
|
|
|
39
|
+
Para MongoDB:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm run prisma:push
|
|
43
|
+
```
|
|
44
|
+
|
|
37
45
|
Execute o seed quando o projeto gerado incluir autenticação por senha:
|
|
38
46
|
|
|
39
47
|
```bash
|
|
@@ -67,7 +75,7 @@ Os testes unitários simulam Prisma e Redis, portanto não exigem serviços reai
|
|
|
67
75
|
npm run test:e2e
|
|
68
76
|
```
|
|
69
77
|
|
|
70
|
-
O script `pretest:e2e` executa `prisma migrate deploy` com `.env.test` antes do início da suíte.
|
|
78
|
+
O script `pretest:e2e` executa `prisma migrate deploy` nos bancos relacionais ou `prisma db push` no MongoDB com `.env.test` antes do início da suíte.
|
|
71
79
|
|
|
72
80
|
Dependendo da estratégia de autenticação gerada, a suíte pode cobrir:
|
|
73
81
|
|
|
@@ -110,11 +118,25 @@ npm test
|
|
|
110
118
|
npm run test:e2e
|
|
111
119
|
```
|
|
112
120
|
|
|
121
|
+
### MongoDB
|
|
122
|
+
|
|
123
|
+
O MongoDB deve funcionar como replica set porque o Prisma usa transações em escritas aninhadas. O Docker Compose gerado configura um replica set de nó único:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
docker compose up -d mongodb
|
|
127
|
+
npm run prisma:push
|
|
128
|
+
npm run build
|
|
129
|
+
npm test
|
|
130
|
+
npm run test:e2e
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use nomes de banco diferentes em `.env` e `.env.test`, como `nestforge` e `nestforge_test`.
|
|
134
|
+
|
|
113
135
|
## Checklist final
|
|
114
136
|
|
|
115
137
|
* [ ] As dependências são instaladas corretamente
|
|
116
138
|
* [ ] O Prisma Client é gerado
|
|
117
|
-
* [ ] As migrations são aplicadas
|
|
139
|
+
* [ ] As migrations são aplicadas ou o schema MongoDB é enviado
|
|
118
140
|
* [ ] O seed executa quando aplicável
|
|
119
141
|
* [ ] O build passa
|
|
120
142
|
* [ ] O lint passa
|
|
@@ -10,6 +10,10 @@ services:
|
|
|
10
10
|
- "3000:3000"
|
|
11
11
|
env_file:
|
|
12
12
|
- .env
|
|
13
|
+
# nestforge:feature:database:mongodb
|
|
14
|
+
environment:
|
|
15
|
+
DATABASE_URL: mongodb://mongodb:27017/nestforge?replicaSet=rs0
|
|
16
|
+
# nestforge:feature:database:mongodb:end
|
|
13
17
|
depends_on:
|
|
14
18
|
# nestforge:feature:database:postgres
|
|
15
19
|
- postgres
|
|
@@ -17,6 +21,9 @@ services:
|
|
|
17
21
|
# nestforge:feature:database:mysql
|
|
18
22
|
- mysql
|
|
19
23
|
# nestforge:feature:database:mysql:end
|
|
24
|
+
# nestforge:feature:database:mongodb
|
|
25
|
+
- mongodb
|
|
26
|
+
# nestforge:feature:database:mongodb:end
|
|
20
27
|
- redis
|
|
21
28
|
volumes:
|
|
22
29
|
- ./src:/app/src
|
|
@@ -53,6 +60,23 @@ services:
|
|
|
53
60
|
- mysql_data:/var/lib/mysql
|
|
54
61
|
# nestforge:feature:database:mysql:end
|
|
55
62
|
|
|
63
|
+
# nestforge:feature:database:mongodb
|
|
64
|
+
mongodb:
|
|
65
|
+
image: mongo:8
|
|
66
|
+
container_name: nestforge-mongodb
|
|
67
|
+
restart: unless-stopped
|
|
68
|
+
command: ["mongod", "--replSet", "rs0", "--bind_ip_all"]
|
|
69
|
+
ports:
|
|
70
|
+
- "27017:27017"
|
|
71
|
+
volumes:
|
|
72
|
+
- mongodb_data:/data/db
|
|
73
|
+
healthcheck:
|
|
74
|
+
test: ["CMD-SHELL", "mongosh --quiet --eval \"try { rs.status().ok } catch (error) { rs.initiate({_id: 'rs0', members: [{_id: 0, host: 'mongodb:27017'}]}).ok }\" | grep 1"]
|
|
75
|
+
interval: 5s
|
|
76
|
+
timeout: 5s
|
|
77
|
+
retries: 10
|
|
78
|
+
# nestforge:feature:database:mongodb:end
|
|
79
|
+
|
|
56
80
|
redis:
|
|
57
81
|
image: redis:7-alpine
|
|
58
82
|
container_name: nestforge-redis
|
|
@@ -75,4 +99,8 @@ volumes:
|
|
|
75
99
|
# nestforge:feature:database:mysql
|
|
76
100
|
volumes:
|
|
77
101
|
mysql_data:
|
|
78
|
-
# nestforge:feature:database:mysql:end
|
|
102
|
+
# nestforge:feature:database:mysql:end
|
|
103
|
+
# nestforge:feature:database:mongodb
|
|
104
|
+
volumes:
|
|
105
|
+
mongodb_data:
|
|
106
|
+
# nestforge:feature:database:mongodb:end
|
|
@@ -1,230 +1,246 @@
|
|
|
1
|
-
# Como adicionar um novo módulo
|
|
2
|
-
|
|
3
|
-
Este guia mostra o passo a passo pra adicionar um recurso novo seguindo as convenções do NestForge, usando um módulo `posts` (posts de blog) como exemplo. Adapte os nomes pro seu caso.
|
|
4
|
-
|
|
5
|
-
## 1. Adicione o model no Prisma
|
|
6
|
-
|
|
7
|
-
Em `prisma/schema.prisma`:
|
|
8
|
-
|
|
9
|
-
```prisma
|
|
10
|
-
model Post {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
-
export
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
@
|
|
183
|
-
@Permissions(Permission.
|
|
184
|
-
|
|
185
|
-
return this.postsService.
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
@
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
1
|
+
# Como adicionar um novo módulo
|
|
2
|
+
|
|
3
|
+
Este guia mostra o passo a passo pra adicionar um recurso novo seguindo as convenções do NestForge, usando um módulo `posts` (posts de blog) como exemplo. Adapte os nomes pro seu caso.
|
|
4
|
+
|
|
5
|
+
## 1. Adicione o model no Prisma
|
|
6
|
+
|
|
7
|
+
Em `prisma/schema.prisma`:
|
|
8
|
+
|
|
9
|
+
```prisma
|
|
10
|
+
model Post {
|
|
11
|
+
// nestforge:feature:database:relational
|
|
12
|
+
id String @id @default(uuid())
|
|
13
|
+
// nestforge:feature:database:relational:end
|
|
14
|
+
// nestforge:feature:database:mongodb
|
|
15
|
+
id String @id @default(auto()) @map("_id") @db.ObjectId
|
|
16
|
+
// nestforge:feature:database:mongodb:end
|
|
17
|
+
title String
|
|
18
|
+
content String
|
|
19
|
+
// nestforge:feature:database:relational
|
|
20
|
+
authorId String
|
|
21
|
+
// nestforge:feature:database:relational:end
|
|
22
|
+
// nestforge:feature:database:mongodb
|
|
23
|
+
authorId String @db.ObjectId
|
|
24
|
+
// nestforge:feature:database:mongodb:end
|
|
25
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
26
|
+
createdAt DateTime @default(now())
|
|
27
|
+
updatedAt DateTime @updatedAt
|
|
28
|
+
|
|
29
|
+
@@map("posts")
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Não esqueça de adicionar a relação inversa no `model User`:
|
|
34
|
+
|
|
35
|
+
```prisma
|
|
36
|
+
posts Post[]
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Em PostgreSQL, MySQL ou SQLite, gere a migration:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx prisma migrate dev --name add_posts
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Em MongoDB, envie o schema diretamente:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm run prisma:push
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## 2. Crie a estrutura de pastas
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
src/posts/
|
|
55
|
+
├── dto/
|
|
56
|
+
│ ├── create-post.dto.ts
|
|
57
|
+
│ └── update-post.dto.ts
|
|
58
|
+
├── entities/
|
|
59
|
+
│ └── post.entity.ts
|
|
60
|
+
├── posts.controller.ts
|
|
61
|
+
├── posts.service.ts
|
|
62
|
+
└── posts.module.ts
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## 3. DTOs com Zod
|
|
66
|
+
|
|
67
|
+
`src/posts/dto/create-post.dto.ts`:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { z } from 'zod';
|
|
71
|
+
import { createZodDto } from 'nestjs-zod';
|
|
72
|
+
|
|
73
|
+
export const createPostSchema = z.object({
|
|
74
|
+
title: z.string().min(3).describe('Título do post'),
|
|
75
|
+
content: z.string().min(10).describe('Conteúdo do post'),
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
export class CreatePostDto extends createZodDto(createPostSchema) {}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`src/posts/dto/update-post.dto.ts`:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import { createZodDto } from 'nestjs-zod';
|
|
85
|
+
import { createPostSchema } from './create-post.dto';
|
|
86
|
+
|
|
87
|
+
export const updatePostSchema = createPostSchema.partial();
|
|
88
|
+
|
|
89
|
+
export class UpdatePostDto extends createZodDto(updatePostSchema) {}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## 4. Entity (o que a API expõe)
|
|
93
|
+
|
|
94
|
+
`src/posts/entities/post.entity.ts` — mesmo se não houver nada sensível pra esconder agora, criar a entity já deixa o padrão pronto pra quando houver:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
export class PostEntity {
|
|
98
|
+
id: string;
|
|
99
|
+
title: string;
|
|
100
|
+
content: string;
|
|
101
|
+
authorId: string;
|
|
102
|
+
createdAt: Date;
|
|
103
|
+
updatedAt: Date;
|
|
104
|
+
|
|
105
|
+
constructor(partial: Partial<PostEntity>) {
|
|
106
|
+
Object.assign(this, partial);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## 5. Service (regra de negócio)
|
|
112
|
+
|
|
113
|
+
`src/posts/posts.service.ts`:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { Injectable, NotFoundException } from '@nestjs/common';
|
|
117
|
+
import { PrismaService } from '../database/prisma.service';
|
|
118
|
+
import { CreatePostDto } from './dto/create-post.dto';
|
|
119
|
+
import { UpdatePostDto } from './dto/update-post.dto';
|
|
120
|
+
import { PostEntity } from './entities/post.entity';
|
|
121
|
+
|
|
122
|
+
@Injectable()
|
|
123
|
+
export class PostsService {
|
|
124
|
+
constructor(private readonly prisma: PrismaService) {}
|
|
125
|
+
|
|
126
|
+
async create(authorId: string, dto: CreatePostDto) {
|
|
127
|
+
const post = await this.prisma.post.create({ data: { ...dto, authorId } });
|
|
128
|
+
return new PostEntity(post);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async findOne(id: string) {
|
|
132
|
+
const post = await this.prisma.post.findUnique({ where: { id } });
|
|
133
|
+
if (!post) throw new NotFoundException('Post não encontrado');
|
|
134
|
+
return new PostEntity(post);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
async update(id: string, dto: UpdatePostDto) {
|
|
138
|
+
await this.findOne(id);
|
|
139
|
+
const post = await this.prisma.post.update({ where: { id }, data: dto });
|
|
140
|
+
return new PostEntity(post);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async remove(id: string) {
|
|
144
|
+
await this.findOne(id);
|
|
145
|
+
await this.prisma.post.delete({ where: { id } });
|
|
146
|
+
return { message: 'Post removido com sucesso' };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## 6. Controller (guards + permissions)
|
|
152
|
+
|
|
153
|
+
Se o recurso precisa de controle de acesso, adicione a permission em `src/common/constants/permissions.ts` e no mapeamento `src/common/constants/role-permissions.ts` antes de usar:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
// permissions.ts
|
|
157
|
+
export enum Permission {
|
|
158
|
+
// ...existentes
|
|
159
|
+
PostCreate = 'post:create',
|
|
160
|
+
PostDelete = 'post:delete',
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`src/posts/posts.controller.ts`:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';
|
|
168
|
+
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
|
169
|
+
import { PostsService } from './posts.service';
|
|
170
|
+
import { CreatePostDto } from './dto/create-post.dto';
|
|
171
|
+
import { UpdatePostDto } from './dto/update-post.dto';
|
|
172
|
+
import { Permissions } from '../common/decorators/permissions.decorator';
|
|
173
|
+
import { Permission } from '../common/constants/permissions';
|
|
174
|
+
import { CurrentUser } from '../common/decorators/current-user.decorator';
|
|
175
|
+
|
|
176
|
+
@ApiTags('posts')
|
|
177
|
+
@ApiBearerAuth()
|
|
178
|
+
@Controller('posts')
|
|
179
|
+
export class PostsController {
|
|
180
|
+
constructor(private readonly postsService: PostsService) {}
|
|
181
|
+
|
|
182
|
+
@Post()
|
|
183
|
+
@Permissions(Permission.PostCreate)
|
|
184
|
+
create(@CurrentUser() user: { id: string }, @Body() dto: CreatePostDto) {
|
|
185
|
+
return this.postsService.create(user.id, dto);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@Get(':id')
|
|
189
|
+
findOne(@Param('id') id: string) {
|
|
190
|
+
return this.postsService.findOne(id);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
@Patch(':id')
|
|
194
|
+
update(@Param('id') id: string, @Body() dto: UpdatePostDto) {
|
|
195
|
+
return this.postsService.update(id, dto);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@Delete(':id')
|
|
199
|
+
@Permissions(Permission.PostDelete)
|
|
200
|
+
remove(@Param('id') id: string) {
|
|
201
|
+
return this.postsService.remove(id);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 7. Module
|
|
207
|
+
|
|
208
|
+
`src/posts/posts.module.ts`:
|
|
209
|
+
|
|
210
|
+
```ts
|
|
211
|
+
import { Module } from '@nestjs/common';
|
|
212
|
+
import { PostsService } from './posts.service';
|
|
213
|
+
import { PostsController } from './posts.controller';
|
|
214
|
+
|
|
215
|
+
@Module({
|
|
216
|
+
controllers: [PostsController],
|
|
217
|
+
providers: [PostsService],
|
|
218
|
+
exports: [PostsService],
|
|
219
|
+
})
|
|
220
|
+
export class PostsModule {}
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Registre no `src/app.module.ts` (dentro do array `imports`):
|
|
224
|
+
|
|
225
|
+
```ts
|
|
226
|
+
import { PostsModule } from './posts/posts.module';
|
|
227
|
+
// ...
|
|
228
|
+
PostsModule,
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## 8. Testes
|
|
232
|
+
|
|
233
|
+
- **Unitário** (`src/posts/posts.service.spec.ts`): mocke o `PrismaService` como em `src/users/users.service.spec.ts` — sem banco real.
|
|
234
|
+
- **E2e** (`test/posts.e2e-spec.ts`): use os helpers de `test/utils/e2e-setup.ts` e `test/utils/clean-database.ts` (adicione `prisma.post.deleteMany()` na limpeza) e siga o padrão de `test/users.e2e-spec.ts`.
|
|
235
|
+
|
|
236
|
+
## Checklist rápido
|
|
237
|
+
|
|
238
|
+
- [ ] Model no `schema.prisma` + migration ou `prisma:push`
|
|
239
|
+
- [ ] DTOs com Zod (`createZodDto`)
|
|
240
|
+
- [ ] Entity (mesmo sem campo sensível ainda)
|
|
241
|
+
- [ ] Service sem lógica no controller
|
|
242
|
+
- [ ] Permissions novas cadastradas em `permissions.ts` e `role-permissions.ts`, se necessário
|
|
243
|
+
- [ ] Module registrado no `AppModule`
|
|
244
|
+
- [ ] Teste unitário do service
|
|
245
|
+
- [ ] Teste e2e do fluxo principal
|
|
246
|
+
- [ ] Atualizar `ROADMAP.md` se o módulo fechar um item do roadmap
|