@nest-arch/tui 0.2.8 → 0.4.3
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 +20 -42
- package/dist/cli.js +1 -1
- package/dist/constants-B5MuV-iH.js +1 -0
- package/dist/index.js +365 -98
- package/dist/templates/addons/husky/pre-commit.hbs +11 -26
- package/dist/templates/base/.env.example.hbs +13 -2
- package/dist/templates/base/.env.hbs +11 -2
- package/dist/templates/base/.gitignore.hbs +2 -1
- package/dist/templates/base/.yarnrc.yml.hbs +0 -5
- package/dist/templates/base/README.md.hbs +49 -5
- package/dist/templates/base/nest-cli.json.hbs +2 -1
- package/dist/templates/base/pnpm-workspace.yaml.hbs +15 -0
- package/dist/templates/base/prisma.config.ts.hbs +32 -6
- package/dist/templates/base/src/app.controller.spec.ts.hbs +3 -11
- package/dist/templates/base/src/app.controller.ts.hbs +2 -2
- package/dist/templates/base/src/app.module.ts.hbs +76 -5
- package/dist/templates/base/src/app.router.ts.hbs +3 -4
- package/dist/templates/base/src/database/adapters/interfaces/db-adapter.interface.ts.hbs +7 -0
- package/dist/templates/base/src/database/adapters/mongo/prisma-mongo.adapter.ts.hbs +36 -4
- package/dist/templates/base/src/database/adapters/mongo/raw-mongo.adapter.ts.hbs +17 -12
- package/dist/templates/base/src/database/adapters/sql/drizzle-sql.adapter.ts.hbs +9 -0
- package/dist/templates/base/src/database/adapters/sql/prisma-sql.adapter.ts.hbs +8 -5
- package/dist/templates/base/src/database/adapters/sql/raw-sql.adapter.ts.hbs +37 -0
- package/dist/templates/base/src/database/adapters/sql/typeorm-sql.adapter.ts.hbs +8 -3
- package/dist/templates/base/src/database/db.module.ts.hbs +55 -42
- package/dist/templates/base/src/database/db.service.ts.hbs +60 -6
- package/dist/templates/base/src/database/entities/app.entity.ts.hbs +25 -0
- package/dist/templates/base/src/database/entities/todo.entity.ts.hbs +12 -7
- package/dist/templates/base/src/database/index.ts.hbs +20 -0
- package/dist/templates/base/src/database/orm/drizzle/schema.ts.hbs +80 -7
- package/dist/templates/base/src/database/orm/typeorm/data-source.ts.hbs +23 -4
- package/dist/templates/base/src/libs/middlewares/auth.trpc.middleware.ts.hbs +47 -0
- package/dist/templates/base/src/libs/middlewares/rate-limit.trpc.middleware.ts.hbs +43 -0
- package/dist/templates/base/src/libs/trpc/error.handler.ts.hbs +1 -1
- package/dist/templates/base/src/libs/trpc/inner.context.ts.hbs +6 -3
- package/dist/templates/base/src/main.ts.hbs +34 -10
- package/dist/templates/base/src/modules/users/entities/user.entity.ts.hbs +22 -0
- package/dist/templates/base/test/app.e2e-spec.ts.hbs +841 -6
- package/dist/templates/base/test/bootstrap.e2e-spec.ts.hbs +84 -0
- package/dist/templates/base/tsconfig.build.json.hbs +2 -0
- package/dist/templates/base/vitest.config.e2e.ts.hbs +4 -3
- package/dist/templates/base/vitest.config.ts.hbs +4 -3
- package/dist/templates/base/yarn.lock.hbs +1 -0
- package/dist/templates/extras/docker/.dockerignore.hbs +8 -1
- package/dist/templates/extras/docker/Dockerfile.hbs +11 -10
- package/dist/templates/extras/health/src/health/health.controller.ts.hbs +54 -0
- package/dist/templates/extras/health/src/health/health.module.ts.hbs +9 -0
- package/dist/templates/extras/swagger/create-docs.ts.hbs +13 -22
- package/dist/templates/feature/graphql/src/graphql/graphql.module.ts.hbs +6 -10
- package/dist/templates/feature/graphql/src/graphql/models/todo.model.ts.hbs +4 -0
- package/dist/templates/feature/graphql/src/graphql/orm/drizzle/drizzle-graphql.module.ts.hbs +6 -4
- package/dist/templates/feature/graphql/src/graphql/resolvers/health.resolver.ts.hbs +14 -0
- package/dist/templates/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +210 -47
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/create-todo.dto.ts.hbs +12 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/update-todo.dto.ts.hbs +12 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.controller.ts.hbs +21 -9
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.module.ts.hbs +1 -3
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.router.ts.hbs +41 -13
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.service.ts.hbs +157 -33
- package/dist/templates/monorepo/apps/api-gateway/package.json.hbs +2 -3
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.spec.ts.hbs +6 -1
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.ts.hbs +6 -0
- package/dist/templates/monorepo/apps/api-gateway/src/app.module.ts.hbs +32 -1
- package/dist/templates/monorepo/apps/api-gateway/src/app.service.ts.hbs +1 -1
- package/dist/templates/monorepo/apps/api-gateway/src/main.ts.hbs +13 -4
- package/dist/templates/monorepo/apps/api-gateway/test/app.e2e-spec.ts.hbs +45 -1
- package/dist/templates/monorepo/apps/api-gateway/tsconfig.build.json.hbs +2 -1
- package/dist/templates/monorepo/apps/api-gateway/vitest.config.e2e.ts.hbs +3 -2
- package/dist/templates/monorepo/apps/api-gateway/vitest.config.ts.hbs +3 -2
- package/dist/templates/monorepo/feature/graphql/src/graphql/graphql.module.ts.hbs +6 -10
- package/dist/templates/monorepo/feature/graphql/src/graphql/resolvers/health.resolver.ts.hbs +14 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +151 -42
- package/dist/templates/monorepo/packages/env/src/api-gateway.ts.hbs +16 -3
- package/dist/templates/monorepo/packages/shared/package.json.hbs +1 -0
- package/dist/templates/monorepo/packages/shared/src/auth.ts.hbs +6 -0
- package/dist/templates/monorepo/root/.gitignore.hbs +1 -0
- package/dist/templates/monorepo/root/pnpm-workspace.yaml.hbs +19 -2
- package/dist/templates/monorepo/root/tsconfig.json.hbs +1 -1
- package/dist/templates/monorepo/root/turbo.json.hbs +2 -0
- package/dist/templates/single-project/architecture/nest-api/.env.hbs +9 -1
- package/dist/templates/single-project/architecture/nest-api/package.json.hbs +1 -2
- package/dist/templates/single-project/architecture/nest-api/src/main.ts.hbs +33 -9
- package/dist/templates/single-project/architecture/nest-gateway/src/main.ts.hbs +3 -3
- package/dist/templates/single-project/architecture/nest-microservice/.env.hbs +18 -0
- package/dist/templates/single-project/architecture/nest-microservice/proto/app.proto.hbs +26 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/app.controller.ts.hbs +23 -4
- package/dist/templates/single-project/architecture/nest-microservice/src/app.service.ts.hbs +6 -2
- package/dist/templates/single-project/architecture/nest-microservice/src/main.ts.hbs +16 -5
- package/dist/templates/single-project/architecture/nest-microservice/test/microservice.e2e-spec.ts.hbs +70 -0
- package/dist/templates/single-project/shared/config/env.ts.hbs +38 -3
- package/package.json +5 -2
- package/dist/constants-Cgtoxhmd.js +0 -1
|
@@ -1,32 +1,76 @@
|
|
|
1
|
-
{{#if (and
|
|
2
|
-
import {
|
|
3
|
-
{{/if}}
|
|
1
|
+
{{#if (and usePrisma (eq auth "none"))}}
|
|
2
|
+
import { BadRequestException, NotFoundException } from "@nestjs/common";
|
|
4
3
|
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
4
|
+
import { DbService } from "../../database/db.service.js";
|
|
5
|
+
import { CreateTodoInput } from "../dto/create-todo.input.js";
|
|
6
|
+
import { UpdateTodoInput } from "../dto/update-todo.input.js";
|
|
7
|
+
import { Todo } from "../models/todo.model.js";
|
|
8
|
+
|
|
9
|
+
@Resolver(() => Todo)
|
|
10
|
+
export class TodoResolver {
|
|
11
|
+
constructor(private readonly db: DbService) {}
|
|
12
|
+
|
|
13
|
+
@Query(() => [Todo])
|
|
14
|
+
todos() {
|
|
15
|
+
return this.db.prisma.todo.findMany({ orderBy: { createdAt: "asc" }, take: 100 });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Mutation(() => Todo)
|
|
19
|
+
createTodo(@Args("input") input: CreateTodoInput) {
|
|
20
|
+
if (!input.title.trim()) throw new BadRequestException("Title must not be empty");
|
|
21
|
+
return this.db.prisma.todo.create({ data: input });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Mutation(() => Todo)
|
|
25
|
+
async updateTodo(@Args("input") input: UpdateTodoInput) {
|
|
26
|
+
const { id, ...data } = input;
|
|
27
|
+
if (data.title !== undefined && !data.title.trim()) throw new BadRequestException("Title must not be empty");
|
|
28
|
+
const result = await this.db.prisma.todo.updateManyAndReturn({ where: { id }, data });
|
|
29
|
+
if (!result[0]) throw new NotFoundException("Todo not found");
|
|
30
|
+
return result[0];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Mutation(() => Boolean)
|
|
34
|
+
async deleteTodo(@Args("id") id: string): Promise<boolean> {
|
|
35
|
+
const result = await this.db.prisma.todo.deleteMany({ where: { id } });
|
|
36
|
+
if (result.count === 0) throw new NotFoundException("Todo not found");
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
{{else}}
|
|
5
41
|
{{#if (and hasAuth hasDatabase)}}
|
|
42
|
+
import { BadRequestException, NotFoundException, UseGuards } from "@nestjs/common";
|
|
6
43
|
import { UserEntity } from "../../auth/decorators/index.js";
|
|
7
44
|
import { GqlAuthGuard } from "../../auth/guards/gql-auth.guard.js";
|
|
45
|
+
{{else}}
|
|
46
|
+
import { BadRequestException, NotFoundException } from "@nestjs/common";
|
|
47
|
+
{{/if}}
|
|
48
|
+
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
49
|
+
{{#if (and hasDatabase useTypeorm)}}
|
|
50
|
+
import { GraphQLResolveInfo } from "graphql";
|
|
51
|
+
import { GraphRelationBuilder } from "typeorm-relations-graphql";
|
|
52
|
+
import { Todo as TodoEntity } from "../../database/entities/todo.entity.js";
|
|
53
|
+
{{/if}}
|
|
54
|
+
{{#if (and hasDatabase useDrizzle)}}
|
|
55
|
+
import { and, eq } from "drizzle-orm";
|
|
56
|
+
import * as schema from "../../database/orm/drizzle/schema.js";
|
|
8
57
|
{{/if}}
|
|
58
|
+
{{#if hasDatabase}}
|
|
9
59
|
{{#if isMonorepo}}
|
|
10
60
|
import { DbService } from "@repo/db";
|
|
11
61
|
{{else}}
|
|
12
62
|
import { DbService } from "../../database/db.service.js";
|
|
13
63
|
{{/if}}
|
|
64
|
+
{{/if}}
|
|
14
65
|
import { CreateTodoInput } from "../dto/create-todo.input.js";
|
|
15
66
|
import { UpdateTodoInput } from "../dto/update-todo.input.js";
|
|
16
|
-
{{#if useTypeorm}}
|
|
17
|
-
import { GraphRelationBuilder } from "typeorm-relations-graphql";
|
|
18
|
-
import { GraphQLResolveInfo } from "graphql";
|
|
19
|
-
{{/if}}
|
|
20
|
-
{{#if useDrizzle}}
|
|
21
|
-
import * as schema from "../../database/orm/drizzle/schema.js";
|
|
22
|
-
{{/if}}
|
|
23
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
24
67
|
import { Todo } from "../models/todo.model.js";
|
|
25
|
-
{{/if}}
|
|
26
68
|
|
|
27
69
|
@Resolver(() => Todo)
|
|
28
70
|
export class TodoResolver {
|
|
71
|
+
{{#if hasDatabase}}
|
|
29
72
|
constructor(private readonly db: DbService) {}
|
|
73
|
+
{{/if}}
|
|
30
74
|
|
|
31
75
|
@Query(() => String)
|
|
32
76
|
hello(): string {
|
|
@@ -34,87 +78,206 @@ export class TodoResolver {
|
|
|
34
78
|
}{{#if hasDatabase}}
|
|
35
79
|
|
|
36
80
|
@Query(() => [Todo])
|
|
37
|
-
|
|
81
|
+
{{#if hasAuth}}
|
|
82
|
+
@UseGuards(GqlAuthGuard)
|
|
83
|
+
{{/if}}
|
|
84
|
+
todos({{#if useTypeorm}}info: GraphQLResolveInfo, {{/if}}{{#if hasAuth}}@UserEntity() user: { id: string }{{/if}}) {
|
|
38
85
|
{{#if useTypeorm}}
|
|
39
|
-
const builder = new GraphRelationBuilder(this.db.
|
|
86
|
+
const builder = new GraphRelationBuilder(this.db.typeorm);
|
|
40
87
|
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
41
|
-
|
|
88
|
+
{{#if hasAuth}}
|
|
89
|
+
return this.db.typeorm.getRepository(TodoEntity).find({ relations, where: { authorId: user.id } });
|
|
90
|
+
{{else}}
|
|
91
|
+
return this.db.typeorm.getRepository(TodoEntity).find({ relations });
|
|
92
|
+
{{/if}}
|
|
93
|
+
{{else if isPrisma8}}
|
|
94
|
+
{{#if hasAuth}}
|
|
95
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ authorId: user.id }).all();
|
|
96
|
+
{{else}}
|
|
97
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
98
|
+
{{/if}}
|
|
42
99
|
{{else if usePrisma}}
|
|
100
|
+
{{#if hasAuth}}
|
|
101
|
+
return this.db.prisma.todo.findMany({ where: { authorId: user.id } });
|
|
102
|
+
{{else}}
|
|
43
103
|
return this.db.prisma.todo.findMany();
|
|
104
|
+
{{/if}}
|
|
44
105
|
{{else if useDrizzle}}
|
|
45
|
-
|
|
106
|
+
{{#if hasAuth}}
|
|
107
|
+
return this.db.drizzle.select().from(schema.todos).where(eq(schema.todos.authorId, user.id));
|
|
108
|
+
{{else}}
|
|
109
|
+
return this.db.drizzle.select().from(schema.todos);
|
|
110
|
+
{{/if}}
|
|
46
111
|
{{else}}
|
|
47
112
|
return [];
|
|
48
113
|
{{/if}}
|
|
49
114
|
}
|
|
50
115
|
|
|
116
|
+
{{#if hasAuth}}
|
|
51
117
|
@UseGuards(GqlAuthGuard)
|
|
118
|
+
{{/if}}
|
|
52
119
|
@Mutation(() => Todo)
|
|
53
|
-
createTodo(
|
|
120
|
+
async createTodo(
|
|
121
|
+
{{#if hasAuth}}
|
|
54
122
|
@UserEntity() user: { id: string },
|
|
123
|
+
{{/if}}
|
|
55
124
|
@Args("input") input: CreateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
56
125
|
) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
126
|
+
if (!input.title.trim()) throw new BadRequestException("Title must not be empty");
|
|
127
|
+
{{#if isPrisma8}}
|
|
128
|
+
{{#if hasAuth}}
|
|
129
|
+
return ((this.db.prisma.orm.public as any).Todo).create({ ...input, authorId: user.id });
|
|
130
|
+
{{else}}
|
|
131
|
+
return ((this.db.prisma.orm.public as any).Todo).create(input);
|
|
132
|
+
{{/if}}
|
|
133
|
+
{{else if usePrisma}}
|
|
134
|
+
{{#if hasAuth}}
|
|
135
|
+
const todo = await this.db.prisma.todo.create({ data: { ...input, authorId: user.id } });
|
|
136
|
+
{{else}}
|
|
137
|
+
const todo = await this.db.prisma.todo.create({ data: input });
|
|
138
|
+
{{/if}}
|
|
139
|
+
return todo;
|
|
140
|
+
{{else if useTypeorm}}
|
|
141
|
+
{{#if hasAuth}}
|
|
142
|
+
const entity = this.db.typeorm.getRepository(TodoEntity).create({ ...input, authorId: user.id });
|
|
143
|
+
{{else}}
|
|
144
|
+
const entity = this.db.typeorm.getRepository(TodoEntity).create(input);
|
|
145
|
+
{{/if}}
|
|
146
|
+
const saved = await this.db.typeorm.getRepository(TodoEntity).save(entity);
|
|
147
|
+
const builder = new GraphRelationBuilder(this.db.typeorm);
|
|
61
148
|
const relations = builder.buildForQuery(Todo, info, "createTodo");
|
|
62
|
-
return this.db.getRepository(
|
|
63
|
-
where: { id: saved.id },
|
|
149
|
+
return this.db.typeorm.getRepository(TodoEntity).findOneOrFail({
|
|
64
150
|
relations,
|
|
65
|
-
|
|
66
|
-
{{else if usePrisma}}
|
|
67
|
-
return this.db.prisma.todo.create({
|
|
68
|
-
data: { ...input, authorId: user.id },
|
|
151
|
+
where: { id: saved.id },
|
|
69
152
|
});
|
|
70
153
|
{{else if useDrizzle}}
|
|
71
|
-
|
|
154
|
+
{{#if hasMysql}}
|
|
155
|
+
const [inserted] = await this.db.drizzle.insert(schema.todos).values({{#if hasAuth}}{ ...input, authorId: user.id }{{else}}input{{/if}}).$returningId();
|
|
156
|
+
if (!inserted) throw new NotFoundException("Todo not found");
|
|
157
|
+
const [todo] = await this.db.drizzle.select().from(schema.todos).where({{#if hasAuth}}and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, inserted.id)){{else}}eq(schema.todos.id, inserted.id){{/if}});
|
|
158
|
+
if (!todo) throw new NotFoundException("Todo not found");
|
|
72
159
|
return todo;
|
|
73
160
|
{{else}}
|
|
161
|
+
{{#if hasAuth}}
|
|
162
|
+
const [todo] = await this.db.drizzle.insert(schema.todos).values({ ...input, authorId: user.id }).returning();
|
|
163
|
+
{{else}}
|
|
164
|
+
const [todo] = await this.db.drizzle.insert(schema.todos).values(input).returning();
|
|
165
|
+
{{/if}}
|
|
166
|
+
if (!todo) throw new NotFoundException("Todo not found");
|
|
167
|
+
return todo;
|
|
168
|
+
{{/if}}
|
|
169
|
+
{{else}}
|
|
74
170
|
return { id: "1", ...input };
|
|
75
171
|
{{/if}}
|
|
76
172
|
}
|
|
77
173
|
|
|
174
|
+
{{#if hasAuth}}
|
|
78
175
|
@UseGuards(GqlAuthGuard)
|
|
176
|
+
{{/if}}
|
|
79
177
|
@Mutation(() => Todo)
|
|
80
|
-
updateTodo(
|
|
178
|
+
async updateTodo(
|
|
179
|
+
{{#if hasAuth}}
|
|
180
|
+
@UserEntity() user: { id: string },
|
|
181
|
+
{{/if}}
|
|
182
|
+
@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
183
|
+
) {
|
|
81
184
|
const { id, ...data } = input;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
185
|
+
if (data.title !== undefined && !data.title.trim()) throw new BadRequestException("Title must not be empty");
|
|
186
|
+
{{#if isPrisma8}}
|
|
187
|
+
{{#if hasAuth}}
|
|
188
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ authorId: user.id, id }).update(data);
|
|
189
|
+
{{else}}
|
|
190
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(data);
|
|
191
|
+
{{/if}}
|
|
192
|
+
{{else if usePrisma}}
|
|
193
|
+
{{#if hasAuth}}
|
|
194
|
+
const result = await this.db.prisma.todo.update({ data, where: { authorId: user.id, id } });
|
|
195
|
+
{{else}}
|
|
196
|
+
const result = await this.db.prisma.todo.update({ data, where: { id } });
|
|
197
|
+
{{/if}}
|
|
198
|
+
return result;
|
|
199
|
+
{{else if useTypeorm}}
|
|
200
|
+
{{#if hasAuth}}
|
|
201
|
+
const updateResult = await this.db.typeorm.getRepository(TodoEntity).update({ authorId: user.id, id }, data);
|
|
202
|
+
{{else}}
|
|
203
|
+
const updateResult = await this.db.typeorm.getRepository(TodoEntity).update(id, data);
|
|
204
|
+
{{/if}}
|
|
205
|
+
if ((updateResult.affected ?? 0) === 0) throw new NotFoundException("Todo not found");
|
|
206
|
+
const builder = new GraphRelationBuilder(this.db.typeorm);
|
|
85
207
|
const relations = builder.buildForQuery(Todo, info, "updateTodo");
|
|
86
|
-
return this.db.getRepository(
|
|
87
|
-
where: { id },
|
|
208
|
+
return this.db.typeorm.getRepository(TodoEntity).findOneOrFail({
|
|
88
209
|
relations,
|
|
210
|
+
where: { id },
|
|
89
211
|
});
|
|
90
|
-
{{else if usePrisma}}
|
|
91
|
-
return this.db.prisma.todo.update({ where: { id }, data });
|
|
92
212
|
{{else if useDrizzle}}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
213
|
+
{{#if hasMysql}}
|
|
214
|
+
await this.db.drizzle.update(schema.todos).set(data).where({{#if hasAuth}}and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id))){{else}}eq(schema.todos.id, Number(id)){{/if}});
|
|
215
|
+
const [todo] = await this.db.drizzle.select().from(schema.todos).where({{#if hasAuth}}and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id))){{else}}eq(schema.todos.id, Number(id)){{/if}});
|
|
216
|
+
{{else}}
|
|
217
|
+
{{#if hasAuth}}
|
|
218
|
+
const [todo] = await this.db.drizzle.update(schema.todos).set(data).where(and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id)))).returning();
|
|
219
|
+
{{else}}
|
|
220
|
+
const [todo] = await this.db.drizzle.update(schema.todos).set(data).where(eq(schema.todos.id, Number(id))).returning();
|
|
221
|
+
{{/if}}
|
|
222
|
+
{{/if}}
|
|
223
|
+
if (!todo) throw new NotFoundException("Todo not found");
|
|
98
224
|
return todo;
|
|
99
225
|
{{else}}
|
|
100
226
|
return { id, ...data };
|
|
101
227
|
{{/if}}
|
|
102
228
|
}
|
|
103
229
|
|
|
230
|
+
{{#if hasAuth}}
|
|
104
231
|
@UseGuards(GqlAuthGuard)
|
|
232
|
+
{{/if}}
|
|
105
233
|
@Mutation(() => Boolean)
|
|
106
|
-
async deleteTodo(
|
|
107
|
-
{{#if
|
|
108
|
-
|
|
109
|
-
|
|
234
|
+
async deleteTodo(
|
|
235
|
+
{{#if hasAuth}}
|
|
236
|
+
@UserEntity() user: { id: string },
|
|
237
|
+
{{/if}}
|
|
238
|
+
@Args("id") id: string
|
|
239
|
+
): Promise<boolean> {
|
|
240
|
+
{{#if isPrisma8}}
|
|
241
|
+
{{#if hasAuth}}
|
|
242
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ authorId: user.id, id }).delete();
|
|
243
|
+
{{else}}
|
|
244
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ id }).delete();
|
|
245
|
+
{{/if}}
|
|
246
|
+
return true;
|
|
110
247
|
{{else if usePrisma}}
|
|
111
|
-
|
|
248
|
+
{{#if hasAuth}}
|
|
249
|
+
const result = await this.db.prisma.todo.deleteMany({ where: { authorId: user.id, id } });
|
|
250
|
+
{{else}}
|
|
251
|
+
const result = await this.db.prisma.todo.deleteMany({ where: { id } });
|
|
252
|
+
{{/if}}
|
|
253
|
+
if (result.count === 0) throw new NotFoundException("Todo not found");
|
|
254
|
+
return true;
|
|
255
|
+
{{else if useTypeorm}}
|
|
256
|
+
{{#if hasAuth}}
|
|
257
|
+
const result = await this.db.typeorm.getRepository(TodoEntity).delete({ authorId: user.id, id });
|
|
258
|
+
{{else}}
|
|
259
|
+
const result = await this.db.typeorm.getRepository(TodoEntity).delete(id);
|
|
260
|
+
{{/if}}
|
|
261
|
+
if ((result.affected ?? 0) === 0) throw new NotFoundException("Todo not found");
|
|
112
262
|
return true;
|
|
113
263
|
{{else if useDrizzle}}
|
|
114
|
-
|
|
264
|
+
{{#if hasMysql}}
|
|
265
|
+
const [existing] = await this.db.drizzle.select().from(schema.todos).where({{#if hasAuth}}and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id))){{else}}eq(schema.todos.id, Number(id)){{/if}});
|
|
266
|
+
if (!existing) throw new NotFoundException("Todo not found");
|
|
267
|
+
await this.db.drizzle.delete(schema.todos).where({{#if hasAuth}}and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id))){{else}}eq(schema.todos.id, Number(id)){{/if}});
|
|
268
|
+
{{else}}
|
|
269
|
+
{{#if hasAuth}}
|
|
270
|
+
const deleted = await this.db.drizzle.delete(schema.todos).where(and(eq(schema.todos.authorId, user.id), eq(schema.todos.id, Number(id)))).returning();
|
|
271
|
+
{{else}}
|
|
272
|
+
const deleted = await this.db.drizzle.delete(schema.todos).where(eq(schema.todos.id, Number(id))).returning();
|
|
273
|
+
{{/if}}
|
|
274
|
+
if (deleted.length === 0) throw new NotFoundException("Todo not found");
|
|
275
|
+
{{/if}}
|
|
115
276
|
return true;
|
|
116
277
|
{{else}}
|
|
117
278
|
return true;
|
|
118
279
|
{{/if}}
|
|
119
280
|
}{{/if}}
|
|
120
281
|
}
|
|
282
|
+
|
|
283
|
+
{{/if}}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
4
|
+
import { createZodDto } from "nestjs-zod";
|
|
5
|
+
|
|
6
|
+
const createTodoSchema = z.object({
|
|
7
|
+
completed: z.boolean().default(false),
|
|
8
|
+
description: z.string().optional(),
|
|
9
|
+
title: z.string().min(1),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export class CreateTodoDto extends createZodDto(createTodoSchema) {}
|
|
13
|
+
{{else}}
|
|
3
14
|
export class CreateTodoDto {
|
|
4
15
|
static schema = z.object({
|
|
5
16
|
completed: z.boolean().default(false),
|
|
@@ -11,3 +22,4 @@ export class CreateTodoDto {
|
|
|
11
22
|
description?: string;
|
|
12
23
|
completed: boolean;
|
|
13
24
|
}
|
|
25
|
+
{{/if}}
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
|
|
3
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
4
|
+
import { createZodDto } from "nestjs-zod";
|
|
5
|
+
|
|
6
|
+
const updateTodoSchema = z.object({
|
|
7
|
+
completed: z.boolean().optional(),
|
|
8
|
+
description: z.string().optional(),
|
|
9
|
+
title: z.string().min(1).optional(),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export class UpdateTodoDto extends createZodDto(updateTodoSchema) {}
|
|
13
|
+
{{else}}
|
|
3
14
|
export class UpdateTodoDto {
|
|
4
15
|
static schema = z.object({
|
|
5
16
|
completed: z.boolean().optional(),
|
|
@@ -11,3 +22,4 @@ export class UpdateTodoDto {
|
|
|
11
22
|
description?: string;
|
|
12
23
|
completed?: boolean;
|
|
13
24
|
}
|
|
25
|
+
{{/if}}
|
|
@@ -9,6 +9,9 @@ import {
|
|
|
9
9
|
{{#if (and isPassportAuth hasDatabase)}}
|
|
10
10
|
UseGuards,
|
|
11
11
|
{{/if}}
|
|
12
|
+
{{#if (and isBetterAuth hasDatabase hasGraphql)}}
|
|
13
|
+
UseGuards,
|
|
14
|
+
{{/if}}
|
|
12
15
|
} from "@nestjs/common";
|
|
13
16
|
{{#if swagger}}
|
|
14
17
|
import {
|
|
@@ -16,10 +19,12 @@ import {
|
|
|
16
19
|
ApiOkResponse,
|
|
17
20
|
ApiOperation,
|
|
18
21
|
ApiTags,
|
|
22
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
19
23
|
ApiUnauthorizedResponse,
|
|
24
|
+
{{/if}}
|
|
20
25
|
} from "@nestjs/swagger";
|
|
21
26
|
{{/if}}
|
|
22
|
-
{{#if isPassportAuth}}
|
|
27
|
+
{{#if (and isPassportAuth swagger)}}
|
|
23
28
|
import {
|
|
24
29
|
ApiBearerAuth,
|
|
25
30
|
} from "@nestjs/swagger";
|
|
@@ -32,6 +37,9 @@ import type { UserSession } from "../../auth/auth.js";
|
|
|
32
37
|
import { RestAuthGuard } from "../../auth/guards/rest-auth.guard.js";
|
|
33
38
|
import { CurrentUser } from "../../auth/decorators/current-user.decorator.js";
|
|
34
39
|
{{/if}}
|
|
40
|
+
{{#if (and isBetterAuth hasDatabase hasGraphql)}}
|
|
41
|
+
import { RestAuthGuard } from "../../auth/guards/rest-auth.guard.js";
|
|
42
|
+
{{/if}}
|
|
35
43
|
import { TodoService } from "./todo.service.js";
|
|
36
44
|
import { CreateTodoDto } from "./dto/create-todo.dto.js";
|
|
37
45
|
import { UpdateTodoDto } from "./dto/update-todo.dto.js";
|
|
@@ -40,7 +48,7 @@ import { UpdateTodoDto } from "./dto/update-todo.dto.js";
|
|
|
40
48
|
@ApiTags("Todos")
|
|
41
49
|
{{/if}}
|
|
42
50
|
@Controller("todos")
|
|
43
|
-
{{#if (and isPassportAuth hasDatabase)}}
|
|
51
|
+
{{#if (or (and isPassportAuth hasDatabase) (and isBetterAuth hasDatabase hasGraphql))}}
|
|
44
52
|
@UseGuards(RestAuthGuard)
|
|
45
53
|
{{/if}}
|
|
46
54
|
export class TodoController {
|
|
@@ -62,7 +70,11 @@ export class TodoController {
|
|
|
62
70
|
return this.todoService.findAll(user.id);
|
|
63
71
|
}
|
|
64
72
|
{{else if (and isBetterAuth hasDatabase)}}
|
|
73
|
+
{{#if (and isMonorepo usePrisma)}}
|
|
74
|
+
findAll(@Session() session: UserSession): ReturnType<TodoService["findAll"]> {
|
|
75
|
+
{{else}}
|
|
65
76
|
findAll(@Session() session: UserSession) {
|
|
77
|
+
{{/if}}
|
|
66
78
|
return this.todoService.findAll(session.user.id);
|
|
67
79
|
}
|
|
68
80
|
{{else}}
|
|
@@ -84,20 +96,20 @@ export class TodoController {
|
|
|
84
96
|
{{/if}}
|
|
85
97
|
{{#if (and isPassportAuth hasDatabase)}}
|
|
86
98
|
create(
|
|
87
|
-
@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto,
|
|
99
|
+
@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: CreateTodoDto.schema }){{/if}} input: CreateTodoDto,
|
|
88
100
|
@CurrentUser() user: { id: string }
|
|
89
101
|
) {
|
|
90
102
|
return this.todoService.create(input, user.id);
|
|
91
103
|
}
|
|
92
104
|
{{else if (and isBetterAuth hasDatabase)}}
|
|
93
105
|
create(
|
|
94
|
-
@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto,
|
|
106
|
+
@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: CreateTodoDto.schema }){{/if}} input: CreateTodoDto,
|
|
95
107
|
@Session() session: UserSession
|
|
96
108
|
) {
|
|
97
109
|
return this.todoService.create(input, session.user.id);
|
|
98
110
|
}
|
|
99
111
|
{{else}}
|
|
100
|
-
create(@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto) {
|
|
112
|
+
create(@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: CreateTodoDto.schema }){{/if}} input: CreateTodoDto) {
|
|
101
113
|
return this.todoService.create(input);
|
|
102
114
|
}
|
|
103
115
|
{{/if}}
|
|
@@ -116,7 +128,7 @@ export class TodoController {
|
|
|
116
128
|
{{#if (and isPassportAuth hasDatabase)}}
|
|
117
129
|
update(
|
|
118
130
|
@Param("id") id: string,
|
|
119
|
-
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto,
|
|
131
|
+
@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: UpdateTodoDto.schema }){{/if}} input: UpdateTodoDto,
|
|
120
132
|
@CurrentUser() user: { id: string }
|
|
121
133
|
) {
|
|
122
134
|
return this.todoService.update(id, input, user.id);
|
|
@@ -124,7 +136,7 @@ export class TodoController {
|
|
|
124
136
|
{{else if (and isBetterAuth hasDatabase)}}
|
|
125
137
|
update(
|
|
126
138
|
@Param("id") id: string,
|
|
127
|
-
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto,
|
|
139
|
+
@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: UpdateTodoDto.schema }){{/if}} input: UpdateTodoDto,
|
|
128
140
|
@Session() session: UserSession
|
|
129
141
|
) {
|
|
130
142
|
return this.todoService.update(id, input, session.user.id);
|
|
@@ -132,7 +144,7 @@ export class TodoController {
|
|
|
132
144
|
{{else}}
|
|
133
145
|
update(
|
|
134
146
|
@Param("id") id: string,
|
|
135
|
-
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto
|
|
147
|
+
@Body{{#if (includes addons "nestjs-zod")}}(){{else}}({ schema: UpdateTodoDto.schema }){{/if}} input: UpdateTodoDto
|
|
136
148
|
) {
|
|
137
149
|
return this.todoService.update(id, input);
|
|
138
150
|
}
|
|
@@ -164,7 +176,7 @@ export class TodoController {
|
|
|
164
176
|
return this.todoService.delete(id, session.user.id);
|
|
165
177
|
}
|
|
166
178
|
{{else}}
|
|
167
|
-
|
|
179
|
+
delete(@Param("id") id: string) {
|
|
168
180
|
return this.todoService.delete(id);
|
|
169
181
|
}
|
|
170
182
|
{{/if}}
|
|
@@ -11,14 +11,12 @@ import { TodoRouter } from "./todo.router.js";
|
|
|
11
11
|
{{#if hasRest}}
|
|
12
12
|
controllers: [TodoController],
|
|
13
13
|
{{/if}}
|
|
14
|
+
exports: [TodoService],
|
|
14
15
|
providers: [
|
|
15
16
|
TodoService,
|
|
16
17
|
{{#unless hasRest}}
|
|
17
18
|
TodoRouter,
|
|
18
19
|
{{/unless}}
|
|
19
20
|
],
|
|
20
|
-
{{#if hasRest}}
|
|
21
|
-
exports: [TodoService],
|
|
22
|
-
{{/if}}
|
|
23
21
|
})
|
|
24
22
|
export class TodoModule {}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{{#if hasTrpc}}
|
|
2
|
-
import { Router, Query, Mutation, Ctx, Input } from "nestjs-trpc";
|
|
2
|
+
import { Router, Query, Mutation, Ctx, Input{{#if hasTrpcAndAuth}}, UseMiddlewares{{/if}} } from "nestjs-trpc";
|
|
3
|
+
import { NotFoundException } from "@nestjs/common";
|
|
4
|
+
import { TRPCError } from "@trpc/server";
|
|
3
5
|
import z from "zod";
|
|
4
|
-
{{#if hasTrpcAndAuth}}
|
|
6
|
+
{{#if (and hasTrpcAndAuth isBetterAuth)}}
|
|
5
7
|
import type { UserSession } from "../../auth/auth.js";
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if hasTrpcAndAuth}}
|
|
6
10
|
import { AuthTRPCMiddleware } from "../../libs/middlewares/auth.trpc.middleware.js";
|
|
7
11
|
import type { InnerContext } from "../../libs/trpc/inner.context.js";
|
|
8
12
|
{{/if}}
|
|
@@ -11,7 +15,7 @@ import { CreateTodoDto } from "./dto/create-todo.dto.js";
|
|
|
11
15
|
import { UpdateTodoDto } from "./dto/update-todo.dto.js";
|
|
12
16
|
|
|
13
17
|
const todoSchema = z.object({
|
|
14
|
-
id: z.string(),
|
|
18
|
+
id: z.union([z.string(), z.number()]),
|
|
15
19
|
title: z.string(),
|
|
16
20
|
description: z.string().nullable().optional(),
|
|
17
21
|
completed: z.boolean(),
|
|
@@ -19,7 +23,7 @@ const todoSchema = z.object({
|
|
|
19
23
|
});
|
|
20
24
|
|
|
21
25
|
const updateTodoInput = z.object({
|
|
22
|
-
id: z.string(),
|
|
26
|
+
id: z.union([z.string(), z.number()]),
|
|
23
27
|
data: UpdateTodoDto.schema,
|
|
24
28
|
});
|
|
25
29
|
|
|
@@ -42,14 +46,26 @@ export class TodoRouter {
|
|
|
42
46
|
|
|
43
47
|
@Mutation({ input: updateTodoInput, output: todoSchema })
|
|
44
48
|
@UseMiddlewares(AuthTRPCMiddleware)
|
|
45
|
-
update(@Ctx() ctx: InnerContext, @Input() input: { id: string; data: UpdateTodoDto }) {
|
|
46
|
-
return this.todoService.update(input.id, input.data, ctx.session!.user.id)
|
|
49
|
+
update(@Ctx() ctx: InnerContext, @Input() input: { id: string | number; data: UpdateTodoDto }) {
|
|
50
|
+
return this.todoService.update(String(input.id), input.data, ctx.session!.user.id)
|
|
51
|
+
.catch((error: unknown) => {
|
|
52
|
+
if (error instanceof NotFoundException) {
|
|
53
|
+
throw new TRPCError({ code: "NOT_FOUND", message: error.message });
|
|
54
|
+
}
|
|
55
|
+
throw error;
|
|
56
|
+
});
|
|
47
57
|
}
|
|
48
58
|
|
|
49
|
-
@Mutation({ input: z.object({ id: z.string() }) })
|
|
59
|
+
@Mutation({ input: z.object({ id: z.union([z.string(), z.number()]) }) })
|
|
50
60
|
@UseMiddlewares(AuthTRPCMiddleware)
|
|
51
|
-
delete(@Ctx() ctx: InnerContext, @Input() input: { id: string }) {
|
|
52
|
-
return this.todoService.delete(input.id, ctx.session!.user.id)
|
|
61
|
+
delete(@Ctx() ctx: InnerContext, @Input() input: { id: string | number }) {
|
|
62
|
+
return this.todoService.delete(String(input.id), ctx.session!.user.id)
|
|
63
|
+
.catch((error: unknown) => {
|
|
64
|
+
if (error instanceof NotFoundException) {
|
|
65
|
+
throw new TRPCError({ code: "NOT_FOUND", message: error.message });
|
|
66
|
+
}
|
|
67
|
+
throw error;
|
|
68
|
+
});
|
|
53
69
|
}
|
|
54
70
|
{{else}}
|
|
55
71
|
@Query({ output: z.array(todoSchema) })
|
|
@@ -64,12 +80,24 @@ export class TodoRouter {
|
|
|
64
80
|
|
|
65
81
|
@Mutation({ input: updateTodoInput, output: todoSchema })
|
|
66
82
|
update(@Input() input: { id: string; data: UpdateTodoDto }) {
|
|
67
|
-
return this.todoService.update(input.id, input.data)
|
|
83
|
+
return this.todoService.update(input.id, input.data)
|
|
84
|
+
.catch((error: unknown) => {
|
|
85
|
+
if (error instanceof NotFoundException) {
|
|
86
|
+
throw new TRPCError({ code: "NOT_FOUND", message: error.message });
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
});
|
|
68
90
|
}
|
|
69
91
|
|
|
70
|
-
@Mutation({ input: z.object({ id: z.string() }) })
|
|
71
|
-
delete(@Input() input: { id: string }) {
|
|
72
|
-
return this.todoService.delete(input.id)
|
|
92
|
+
@Mutation({ input: z.object({ id: z.union([z.string(), z.number()]) }) })
|
|
93
|
+
delete(@Input() input: { id: string | number }) {
|
|
94
|
+
return this.todoService.delete(String(input.id))
|
|
95
|
+
.catch((error: unknown) => {
|
|
96
|
+
if (error instanceof NotFoundException) {
|
|
97
|
+
throw new TRPCError({ code: "NOT_FOUND", message: error.message });
|
|
98
|
+
}
|
|
99
|
+
throw error;
|
|
100
|
+
});
|
|
73
101
|
}
|
|
74
102
|
{{/if}}
|
|
75
103
|
}
|