@nest-arch/tui 0.1.48 → 0.2.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.
- package/README.md +7 -0
- package/dist/cli.js +1 -1
- package/dist/constants-LZTzRAoQ.js +1 -0
- package/dist/index.js +97 -79
- package/dist/templates/base/.env.example.hbs +36 -0
- package/dist/templates/base/.env.hbs +7 -0
- package/dist/templates/base/.gitignore.hbs +3 -0
- package/dist/templates/base/README.md.hbs +119 -6
- package/dist/templates/base/pnpm-workspace.yaml.hbs +9 -0
- package/dist/templates/base/src/app.controller.ts.hbs +10 -0
- package/dist/templates/base/src/app.module.ts.hbs +48 -5
- package/dist/templates/base/src/app.router.spec.ts.hbs +58 -0
- package/dist/templates/base/src/app.router.ts.hbs +26 -0
- package/dist/templates/base/src/database/adapters/interfaces/db-adapter.interface.ts.hbs +3 -3
- package/dist/templates/base/src/libs/middlewares/auth.trpc.middleware.ts.hbs +42 -0
- package/dist/templates/base/src/libs/trpc/context.ts.hbs +13 -0
- package/dist/templates/base/src/libs/trpc/error.handler.ts.hbs +10 -0
- package/dist/templates/base/src/libs/trpc/inner.context.ts.hbs +7 -0
- package/dist/templates/base/src/libs/trpc/protected.ts.hbs +12 -0
- package/dist/templates/base/src/libs/trpc/scripts/fix-trpc-generated.mjs.hbs +21 -0
- package/dist/templates/base/src/libs/trpc/scripts/watch-trpc.mjs.hbs +91 -0
- package/dist/templates/base/src/main.ts.hbs +78 -1
- package/dist/templates/extras/swagger/create-docs.ts.hbs +276 -0
- package/dist/templates/feature/graphql/src/graphql/dto/create-todo.input.ts.hbs +13 -0
- package/dist/templates/feature/graphql/src/graphql/dto/update-todo.input.ts.hbs +8 -0
- package/dist/templates/feature/graphql/src/graphql/graphql.module.ts.hbs +33 -0
- package/dist/templates/feature/graphql/src/graphql/models/base.model.ts.hbs +13 -0
- package/dist/templates/feature/graphql/src/graphql/models/pagination.model.ts.hbs +27 -0
- package/dist/templates/feature/graphql/src/graphql/models/todo.model.ts.hbs +23 -0
- package/dist/templates/feature/graphql/src/graphql/models/user.model.ts.hbs +34 -0
- package/dist/templates/feature/graphql/src/graphql/orm/drizzle/drizzle-graphql.module.ts.hbs +42 -0
- package/dist/templates/feature/graphql/src/graphql/orm/typeorm/typeorm-graphql-relations.helper.ts.hbs +23 -0
- package/dist/templates/feature/graphql/src/graphql/resolvers/base.resolver.ts.hbs +50 -0
- package/dist/templates/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +126 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/create-todo.dto.ts.hbs +13 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/update-todo.dto.ts.hbs +13 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.controller.ts.hbs +346 -0
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.ts.hbs +10 -0
- package/dist/templates/monorepo/apps/api-gateway/src/app.module.ts.hbs +41 -2
- package/dist/templates/monorepo/apps/api-gateway/src/main.ts.hbs +75 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/dto/create-todo.input.ts.hbs +13 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/dto/update-todo.input.ts.hbs +8 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/graphql.module.ts.hbs +33 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/models/base.model.ts.hbs +13 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/models/todo.model.ts.hbs +23 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/models/user.model.ts.hbs +34 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/orm/drizzle/drizzle-graphql.module.ts.hbs +16 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/orm/prisma/prisma-graphql.service.ts.hbs +9 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/orm/typeorm/typeorm-graphql-relations.helper.ts.hbs +23 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +122 -0
- package/dist/templates/monorepo/packages/env/src/api-gateway.ts.hbs +10 -0
- package/dist/templates/monorepo/root/README.md.hbs +1 -1
- package/dist/templates/monorepo/root/pnpm-workspace.yaml.hbs +9 -0
- package/dist/templates/single-project/architecture/nest-api/.env.hbs +25 -1
- package/dist/templates/single-project/architecture/nest-api/pnpm-workspace.yaml.hbs +9 -0
- package/dist/templates/single-project/architecture/nest-api/src/main.ts.hbs +79 -0
- package/dist/templates/single-project/architecture/nest-gateway/src/main.ts.hbs +75 -0
- package/dist/templates/single-project/architecture/nest-microservice/.env.hbs +3 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/main.ts.hbs +76 -0
- package/dist/templates/single-project/shared/config/env.ts.hbs +10 -0
- package/package.json +3 -3
- package/dist/constants-D_Ow0fiZ.js +0 -1
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
2
|
+
import { UseGuards } from "@nestjs/common";
|
|
3
|
+
{{/if}}
|
|
4
|
+
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
5
|
+
import { CreateTodoInput } from "../dto/create-todo.input.js";
|
|
6
|
+
import { UpdateTodoInput } from "../dto/update-todo.input.js";
|
|
7
|
+
{{#if isMonorepo}}
|
|
8
|
+
import { DbService } from "@repo/db";
|
|
9
|
+
{{else}}
|
|
10
|
+
import { DbService } from "../database/db.service.js";
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if useTypeorm}}
|
|
13
|
+
import { GraphRelationBuilder } from "typeorm-relations-graphql";
|
|
14
|
+
import { GraphQLResolveInfo } from "graphql";
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if useDrizzle}}
|
|
17
|
+
import * as schema from "../database/orm/drizzle/schema.js";
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
20
|
+
import { Todo } from "../models/todo.model.js";
|
|
21
|
+
import { UserEntity } from "../../auth/decorators/index.js";
|
|
22
|
+
import { GqlAuthGuard } from "../../auth/guards/gql-auth.guard.js";
|
|
23
|
+
{{/if}}
|
|
24
|
+
|
|
25
|
+
@Resolver({{#if (and hasAuth hasDatabase)}}{{"("}}() => Todo){{/if}})
|
|
26
|
+
export class TodoResolver {
|
|
27
|
+
constructor(private readonly db: DbService) {}
|
|
28
|
+
|
|
29
|
+
@Query(() => String)
|
|
30
|
+
hello(): string {
|
|
31
|
+
return "Hello GraphQL!";
|
|
32
|
+
}{{#if hasDatabase}}
|
|
33
|
+
|
|
34
|
+
@Query(() => [Todo])
|
|
35
|
+
todos({{#if useTypeorm}}info: GraphQLResolveInfo{{/if}}): Promise<Todo[]> {
|
|
36
|
+
{{#if useTypeorm}}
|
|
37
|
+
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
38
|
+
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
39
|
+
return this.db.getRepository(Todo).find({ relations });
|
|
40
|
+
{{else if usePrisma}}
|
|
41
|
+
return this.db.prisma.todo.findMany();
|
|
42
|
+
{{else if useDrizzle}}
|
|
43
|
+
return this.db.select().from(schema.todos);
|
|
44
|
+
{{else}}
|
|
45
|
+
return [];
|
|
46
|
+
{{/if}}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Mutation(() => Todo)
|
|
50
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
51
|
+
@UseGuards(GqlAuthGuard)
|
|
52
|
+
{{/if}}
|
|
53
|
+
createTodo(
|
|
54
|
+
@Args("input") input: CreateTodoInput{{#if (and hasAuth hasDatabase)}},
|
|
55
|
+
@UserEntity() user: { id: string }{{/if}}{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
56
|
+
): Promise<Todo> {
|
|
57
|
+
{{#if useTypeorm}}
|
|
58
|
+
const entity = this.db.getRepository(Todo).create(input);
|
|
59
|
+
const saved = await this.db.getRepository(Todo).save(entity);
|
|
60
|
+
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
61
|
+
const relations = builder.buildForQuery(Todo, info, "createTodo");
|
|
62
|
+
return this.db.getRepository(Todo).findOneOrFail({
|
|
63
|
+
where: { id: saved.id },
|
|
64
|
+
relations,
|
|
65
|
+
});
|
|
66
|
+
{{else if usePrisma}}
|
|
67
|
+
return this.db.prisma.todo.create({
|
|
68
|
+
data: { ...input{{#if (and hasAuth hasDatabase)}}, authorId: user.id{{/if}} },
|
|
69
|
+
});
|
|
70
|
+
{{else if useDrizzle}}
|
|
71
|
+
const [todo] = await this.db.insert(schema.todos).values(input).returning();
|
|
72
|
+
return todo;
|
|
73
|
+
{{else}}
|
|
74
|
+
return { id: "1", ...input };
|
|
75
|
+
{{/if}}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@Mutation(() => Todo)
|
|
79
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
80
|
+
@UseGuards(GqlAuthGuard)
|
|
81
|
+
{{/if}}
|
|
82
|
+
updateTodo(
|
|
83
|
+
@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
84
|
+
): Promise<Todo> {
|
|
85
|
+
const { id, ...data } = input;
|
|
86
|
+
{{#if useTypeorm}}
|
|
87
|
+
await this.db.getRepository(Todo).update(id, data);
|
|
88
|
+
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
89
|
+
const relations = builder.buildForQuery(Todo, info, "updateTodo");
|
|
90
|
+
return this.db.getRepository(Todo).findOneOrFail({
|
|
91
|
+
where: { id },
|
|
92
|
+
relations,
|
|
93
|
+
});
|
|
94
|
+
{{else if usePrisma}}
|
|
95
|
+
return this.db.prisma.todo.update({ where: { id }, data });
|
|
96
|
+
{{else if useDrizzle}}
|
|
97
|
+
const [todo] = await this.db
|
|
98
|
+
.update(schema.todos)
|
|
99
|
+
.set(data)
|
|
100
|
+
.where(eq(schema.todos.id, id))
|
|
101
|
+
.returning();
|
|
102
|
+
return todo;
|
|
103
|
+
{{else}}
|
|
104
|
+
return { id, ...data };
|
|
105
|
+
{{/if}}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@Mutation(() => Boolean)
|
|
109
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
110
|
+
@UseGuards(GqlAuthGuard)
|
|
111
|
+
{{/if}}
|
|
112
|
+
async deleteTodo(@Args("id") id: string): Promise<boolean> {
|
|
113
|
+
{{#if useTypeorm}}
|
|
114
|
+
const result = await this.db.getRepository(Todo).delete(id);
|
|
115
|
+
return (result.affected ?? 0) > 0;
|
|
116
|
+
{{else if usePrisma}}
|
|
117
|
+
await this.db.prisma.todo.delete({ where: { id } });
|
|
118
|
+
return true;
|
|
119
|
+
{{else if useDrizzle}}
|
|
120
|
+
await this.db.delete(schema.todos).where(eq(schema.todos.id, id));
|
|
121
|
+
return true;
|
|
122
|
+
{{else}}
|
|
123
|
+
return true;
|
|
124
|
+
{{/if}}
|
|
125
|
+
}{{/if}}
|
|
126
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export class CreateTodoDto {
|
|
4
|
+
static schema = z.object({
|
|
5
|
+
completed: z.boolean().default(false),
|
|
6
|
+
description: z.string().optional(),
|
|
7
|
+
title: z.string().min(1),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
title: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
completed: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export class UpdateTodoDto {
|
|
4
|
+
static schema = z.object({
|
|
5
|
+
completed: z.boolean().optional(),
|
|
6
|
+
description: z.string().optional(),
|
|
7
|
+
title: z.string().min(1).optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
title?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
completed?: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Body,
|
|
3
|
+
Controller,
|
|
4
|
+
Delete,
|
|
5
|
+
Get,
|
|
6
|
+
Param,
|
|
7
|
+
Post,
|
|
8
|
+
Put,
|
|
9
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
10
|
+
UseGuards,
|
|
11
|
+
{{/if}}
|
|
12
|
+
} from "@nestjs/common";
|
|
13
|
+
{{#if swagger}}
|
|
14
|
+
import {
|
|
15
|
+
ApiCreatedResponse,
|
|
16
|
+
ApiOkResponse,
|
|
17
|
+
ApiOperation,
|
|
18
|
+
ApiTags,
|
|
19
|
+
ApiUnauthorizedResponse,
|
|
20
|
+
} from "@nestjs/swagger";
|
|
21
|
+
{{/if}}
|
|
22
|
+
{{#if isPassportAuth}}
|
|
23
|
+
import {
|
|
24
|
+
ApiBearerAuth,
|
|
25
|
+
} from "@nestjs/swagger";
|
|
26
|
+
{{/if}}
|
|
27
|
+
{{#if (and isBetterAuth hasDatabase)}}
|
|
28
|
+
import { Session } from "@thallesp/nestjs-better-auth";
|
|
29
|
+
import type { UserSession } from "../../auth/auth.js";
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if isMonorepo}}
|
|
32
|
+
import { DbService } from "@repo/db";
|
|
33
|
+
{{else if hasDatabase}}
|
|
34
|
+
import { DbService } from "../../database/db.service.js";
|
|
35
|
+
{{/if}}
|
|
36
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
37
|
+
import { RestAuthGuard } from "../../auth/guards/rest-auth.guard.js";
|
|
38
|
+
import { CurrentUser } from "../../auth/decorators/current-user.decorator.js";
|
|
39
|
+
{{/if}}
|
|
40
|
+
{{#if hasDatabase}}
|
|
41
|
+
{{#if useDrizzle}}
|
|
42
|
+
import * as schema from "../../database/orm/drizzle/schema.js";
|
|
43
|
+
import { eq } from "drizzle-orm";
|
|
44
|
+
{{/if}}
|
|
45
|
+
{{#if useTypeorm}}
|
|
46
|
+
import { Todo } from "../../database/entities/todo.entity.js";
|
|
47
|
+
{{/if}}
|
|
48
|
+
{{/if}}
|
|
49
|
+
import { CreateTodoDto } from "./dto/create-todo.dto.js";
|
|
50
|
+
import { UpdateTodoDto } from "./dto/update-todo.dto.js";
|
|
51
|
+
|
|
52
|
+
{{#if swagger}}
|
|
53
|
+
@ApiTags("Todos")
|
|
54
|
+
{{/if}}
|
|
55
|
+
@Controller("todos")
|
|
56
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
57
|
+
@UseGuards(RestAuthGuard)
|
|
58
|
+
{{/if}}
|
|
59
|
+
export class TodoController {
|
|
60
|
+
{{#if hasDatabase}}
|
|
61
|
+
constructor(private readonly db: DbService) {}
|
|
62
|
+
{{else}}
|
|
63
|
+
private todos: Array<{
|
|
64
|
+
completed: boolean;
|
|
65
|
+
description?: string;
|
|
66
|
+
id: string;
|
|
67
|
+
title: string;
|
|
68
|
+
}> = [];
|
|
69
|
+
private nextId = 1;
|
|
70
|
+
{{/if}}
|
|
71
|
+
|
|
72
|
+
@Get()
|
|
73
|
+
{{#if swagger}}
|
|
74
|
+
{{#if (or isPassportAuth)}}
|
|
75
|
+
@ApiBearerAuth()
|
|
76
|
+
{{/if}}
|
|
77
|
+
@ApiOperation({ summary: "/api/todos" })
|
|
78
|
+
@ApiOkResponse({ description: "Returns all todos" })
|
|
79
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
80
|
+
@ApiUnauthorizedResponse({ description: "Unauthorized" })
|
|
81
|
+
{{/if}}
|
|
82
|
+
{{/if}}
|
|
83
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
84
|
+
findAll(@CurrentUser() user: { id: string }) {
|
|
85
|
+
{{#if usePrisma}}
|
|
86
|
+
return this.db.prisma.todo.findMany({ where: { authorId: user.id } });
|
|
87
|
+
{{else if useTypeorm}}
|
|
88
|
+
return this.db.getRepository(Todo).find({ where: { authorId: user.id } });
|
|
89
|
+
{{else if useDrizzle}}
|
|
90
|
+
return this.db
|
|
91
|
+
.select()
|
|
92
|
+
.from(schema.todos)
|
|
93
|
+
.where(eq(schema.todos.authorId, user.id));
|
|
94
|
+
{{/if}}
|
|
95
|
+
}
|
|
96
|
+
{{else if (and isBetterAuth hasDatabase)}}
|
|
97
|
+
findAll(@Session() session: UserSession) {
|
|
98
|
+
{{#if usePrisma}}
|
|
99
|
+
return this.db.prisma.todo.findMany({
|
|
100
|
+
where: { authorId: session.user.id },
|
|
101
|
+
});
|
|
102
|
+
{{else if useTypeorm}}
|
|
103
|
+
return this.db
|
|
104
|
+
.getRepository(Todo)
|
|
105
|
+
.find({ where: { authorId: session.user.id } });
|
|
106
|
+
{{else if useDrizzle}}
|
|
107
|
+
return this.db
|
|
108
|
+
.select()
|
|
109
|
+
.from(schema.todos)
|
|
110
|
+
.where(eq(schema.todos.authorId, session.user.id));
|
|
111
|
+
{{/if}}
|
|
112
|
+
}
|
|
113
|
+
{{else if hasDatabase}}
|
|
114
|
+
findAll() {
|
|
115
|
+
{{#if usePrisma}}
|
|
116
|
+
return this.db.prisma.todo.findMany();
|
|
117
|
+
{{else if useTypeorm}}
|
|
118
|
+
return this.db.getRepository(Todo).find();
|
|
119
|
+
{{else if useDrizzle}}
|
|
120
|
+
return this.db.select().from(schema.todos);
|
|
121
|
+
{{/if}}
|
|
122
|
+
}
|
|
123
|
+
{{else}}
|
|
124
|
+
findAll() {
|
|
125
|
+
return [...this.todos];
|
|
126
|
+
}
|
|
127
|
+
{{/if}}
|
|
128
|
+
|
|
129
|
+
@Post()
|
|
130
|
+
{{#if swagger}}
|
|
131
|
+
{{#if (or isPassportAuth)}}
|
|
132
|
+
@ApiBearerAuth()
|
|
133
|
+
{{/if}}
|
|
134
|
+
@ApiOperation({ summary: "/api/todos" })
|
|
135
|
+
@ApiCreatedResponse({ description: "Todo created successfully" })
|
|
136
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
137
|
+
@ApiUnauthorizedResponse({ description: "Unauthorized" })
|
|
138
|
+
{{/if}}
|
|
139
|
+
{{/if}}
|
|
140
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
141
|
+
create(
|
|
142
|
+
@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto,
|
|
143
|
+
@CurrentUser() user: { id: string }
|
|
144
|
+
) {
|
|
145
|
+
{{#if usePrisma}}
|
|
146
|
+
return this.db.prisma.todo.create({
|
|
147
|
+
data: { ...input, authorId: user.id },
|
|
148
|
+
});
|
|
149
|
+
{{else if useTypeorm}}
|
|
150
|
+
return this.db.getRepository(Todo).save(
|
|
151
|
+
this.db.getRepository(Todo).create({ ...input, authorId: user.id }),
|
|
152
|
+
);
|
|
153
|
+
{{else if useDrizzle}}
|
|
154
|
+
return this.db
|
|
155
|
+
.insert(schema.todos)
|
|
156
|
+
.values({ ...input, authorId: user.id })
|
|
157
|
+
.returning();
|
|
158
|
+
{{/if}}
|
|
159
|
+
}
|
|
160
|
+
{{else if (and isBetterAuth hasDatabase)}}
|
|
161
|
+
create(
|
|
162
|
+
@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto,
|
|
163
|
+
@Session() session: UserSession
|
|
164
|
+
) {
|
|
165
|
+
{{#if usePrisma}}
|
|
166
|
+
return this.db.prisma.todo.create({
|
|
167
|
+
data: { ...input, authorId: session.user.id },
|
|
168
|
+
});
|
|
169
|
+
{{else if useTypeorm}}
|
|
170
|
+
return this.db.getRepository(Todo).save(
|
|
171
|
+
this.db
|
|
172
|
+
.getRepository(Todo)
|
|
173
|
+
.create({ ...input, authorId: session.user.id }),
|
|
174
|
+
);
|
|
175
|
+
{{else if useDrizzle}}
|
|
176
|
+
return this.db
|
|
177
|
+
.insert(schema.todos)
|
|
178
|
+
.values({ ...input, authorId: session.user.id })
|
|
179
|
+
.returning();
|
|
180
|
+
{{/if}}
|
|
181
|
+
}
|
|
182
|
+
{{else if hasDatabase}}
|
|
183
|
+
create(@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto) {
|
|
184
|
+
{{#if usePrisma}}
|
|
185
|
+
return this.db.prisma.todo.create({ data: input });
|
|
186
|
+
{{else if useTypeorm}}
|
|
187
|
+
return this.db
|
|
188
|
+
.getRepository(Todo)
|
|
189
|
+
.save(this.db.getRepository(Todo).create(input));
|
|
190
|
+
{{else if useDrizzle}}
|
|
191
|
+
return this.db.insert(schema.todos).values(input).returning();
|
|
192
|
+
{{/if}}
|
|
193
|
+
}
|
|
194
|
+
{{else}}
|
|
195
|
+
create(@Body({ schema: CreateTodoDto.schema }) input: CreateTodoDto) {
|
|
196
|
+
const todo = { id: String(this.nextId++), ...input };
|
|
197
|
+
this.todos.push(todo);
|
|
198
|
+
return todo;
|
|
199
|
+
}
|
|
200
|
+
{{/if}}
|
|
201
|
+
|
|
202
|
+
@Put(":id")
|
|
203
|
+
{{#if swagger}}
|
|
204
|
+
{{#if (or isPassportAuth)}}
|
|
205
|
+
@ApiBearerAuth()
|
|
206
|
+
{{/if}}
|
|
207
|
+
@ApiOperation({ summary: "/api/todos/{id}" })
|
|
208
|
+
@ApiOkResponse({ description: "Todo updated successfully" })
|
|
209
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
210
|
+
@ApiUnauthorizedResponse({ description: "Unauthorized" })
|
|
211
|
+
{{/if}}
|
|
212
|
+
{{/if}}
|
|
213
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
214
|
+
update(
|
|
215
|
+
@Param("id") id: string,
|
|
216
|
+
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto,
|
|
217
|
+
@CurrentUser() user: { id: string }
|
|
218
|
+
) {
|
|
219
|
+
{{#if usePrisma}}
|
|
220
|
+
return this.db.prisma.todo.update({
|
|
221
|
+
data: input,
|
|
222
|
+
where: { authorId: user.id, id },
|
|
223
|
+
});
|
|
224
|
+
{{else if useTypeorm}}
|
|
225
|
+
return this.db
|
|
226
|
+
.getRepository(Todo)
|
|
227
|
+
.update({ authorId: user.id, id }, input);
|
|
228
|
+
{{else if useDrizzle}}
|
|
229
|
+
return this.db
|
|
230
|
+
.update(schema.todos)
|
|
231
|
+
.set(input)
|
|
232
|
+
.where(
|
|
233
|
+
eq(schema.todos.authorId, user.id) && eq(schema.todos.id, id),
|
|
234
|
+
)
|
|
235
|
+
.returning();
|
|
236
|
+
{{/if}}
|
|
237
|
+
}
|
|
238
|
+
{{else if (and isBetterAuth hasDatabase)}}
|
|
239
|
+
update(
|
|
240
|
+
@Param("id") id: string,
|
|
241
|
+
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto,
|
|
242
|
+
@Session() session: UserSession
|
|
243
|
+
) {
|
|
244
|
+
{{#if usePrisma}}
|
|
245
|
+
return this.db.prisma.todo.update({
|
|
246
|
+
data: input,
|
|
247
|
+
where: { authorId: session.user.id, id },
|
|
248
|
+
});
|
|
249
|
+
{{else if useTypeorm}}
|
|
250
|
+
return this.db
|
|
251
|
+
.getRepository(Todo)
|
|
252
|
+
.update({ authorId: session.user.id, id }, input);
|
|
253
|
+
{{else if useDrizzle}}
|
|
254
|
+
return this.db
|
|
255
|
+
.update(schema.todos)
|
|
256
|
+
.set(input)
|
|
257
|
+
.where(
|
|
258
|
+
eq(schema.todos.authorId, session.user.id) &&
|
|
259
|
+
eq(schema.todos.id, id),
|
|
260
|
+
)
|
|
261
|
+
.returning();
|
|
262
|
+
{{/if}}
|
|
263
|
+
}
|
|
264
|
+
{{else if hasDatabase}}
|
|
265
|
+
update(
|
|
266
|
+
@Param("id") id: string,
|
|
267
|
+
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto
|
|
268
|
+
) {
|
|
269
|
+
{{#if usePrisma}}
|
|
270
|
+
return this.db.prisma.todo.update({ data: input, where: { id } });
|
|
271
|
+
{{else if useTypeorm}}
|
|
272
|
+
return this.db.getRepository(Todo).update(id, input);
|
|
273
|
+
{{else if useDrizzle}}
|
|
274
|
+
return this.db
|
|
275
|
+
.update(schema.todos)
|
|
276
|
+
.set(input)
|
|
277
|
+
.where(eq(schema.todos.id, id))
|
|
278
|
+
.returning();
|
|
279
|
+
{{/if}}
|
|
280
|
+
}
|
|
281
|
+
{{else}}
|
|
282
|
+
update(
|
|
283
|
+
@Param("id") id: string,
|
|
284
|
+
@Body({ schema: UpdateTodoDto.schema }) input: UpdateTodoDto
|
|
285
|
+
) {
|
|
286
|
+
const todo = this.todos.find((t) => t.id === id);
|
|
287
|
+
if (!todo) {
|
|
288
|
+
return { message: "Todo not found" };
|
|
289
|
+
}
|
|
290
|
+
Object.assign(todo, input);
|
|
291
|
+
return todo;
|
|
292
|
+
}
|
|
293
|
+
{{/if}}
|
|
294
|
+
|
|
295
|
+
@Delete(":id")
|
|
296
|
+
{{#if swagger}}
|
|
297
|
+
{{#if (or isPassportAuth)}}
|
|
298
|
+
@ApiBearerAuth()
|
|
299
|
+
{{/if}}
|
|
300
|
+
@ApiOperation({ summary: "/api/todos/{id}" })
|
|
301
|
+
@ApiOkResponse({ description: "Todo deleted successfully" })
|
|
302
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
303
|
+
@ApiUnauthorizedResponse({ description: "Unauthorized" })
|
|
304
|
+
{{/if}}
|
|
305
|
+
{{/if}}
|
|
306
|
+
{{#if (and isPassportAuth hasDatabase)}}
|
|
307
|
+
async delete(
|
|
308
|
+
@Param("id") id: string,
|
|
309
|
+
@CurrentUser() user: { id: string }
|
|
310
|
+
) {
|
|
311
|
+
await this.db.prisma.todo.delete({
|
|
312
|
+
where: { authorId: user.id, id },
|
|
313
|
+
});
|
|
314
|
+
return { message: "Todo deleted successfully" };
|
|
315
|
+
}
|
|
316
|
+
{{else if (and isBetterAuth hasDatabase)}}
|
|
317
|
+
async delete(
|
|
318
|
+
@Param("id") id: string,
|
|
319
|
+
@Session() session: UserSession
|
|
320
|
+
) {
|
|
321
|
+
await this.db.prisma.todo.delete({
|
|
322
|
+
where: { authorId: session.user.id, id },
|
|
323
|
+
});
|
|
324
|
+
return { message: "Todo deleted successfully" };
|
|
325
|
+
}
|
|
326
|
+
{{else if hasDatabase}}
|
|
327
|
+
async delete(@Param("id") id: string) {
|
|
328
|
+
{{#if usePrisma}}
|
|
329
|
+
await this.db.prisma.todo.delete({ where: { id } });
|
|
330
|
+
{{else if useTypeorm}}
|
|
331
|
+
await this.db.getRepository(Todo).delete(id);
|
|
332
|
+
{{else if useDrizzle}}
|
|
333
|
+
await this.db.delete(schema.todos).where(eq(schema.todos.id, id));
|
|
334
|
+
{{/if}}
|
|
335
|
+
return { message: "Todo deleted successfully" };
|
|
336
|
+
}
|
|
337
|
+
{{else}}
|
|
338
|
+
async delete(@Param("id") id: string) {
|
|
339
|
+
const index = this.todos.findIndex((t) => t.id === id);
|
|
340
|
+
if (index >= 0) {
|
|
341
|
+
this.todos.splice(index, 1);
|
|
342
|
+
}
|
|
343
|
+
return { message: "Todo deleted successfully" };
|
|
344
|
+
}
|
|
345
|
+
{{/if}}
|
|
346
|
+
}
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { Controller, Get } from "@nestjs/common";
|
|
2
|
+
{{#if swagger}}
|
|
3
|
+
import { ApiOperation, ApiResponse, ApiTags } from "@nestjs/swagger";
|
|
4
|
+
{{/if}}
|
|
2
5
|
|
|
3
6
|
import { AppService } from "./app.service.js";
|
|
4
7
|
|
|
8
|
+
{{#if swagger}}
|
|
9
|
+
@ApiTags("App")
|
|
10
|
+
{{/if}}
|
|
5
11
|
@Controller()
|
|
6
12
|
export class AppController {
|
|
7
13
|
constructor(private readonly appService: AppService) {}
|
|
8
14
|
|
|
15
|
+
{{#if swagger}}
|
|
16
|
+
@ApiOperation({ summary: "/api" })
|
|
17
|
+
@ApiResponse({ status: 200, description: "Returns a hello world message" })
|
|
18
|
+
{{/if}}
|
|
9
19
|
@Get()
|
|
10
20
|
getHello(): string {
|
|
11
21
|
return this.appService.getHello();
|
|
@@ -6,12 +6,32 @@ import { env } from "./config/env.js";
|
|
|
6
6
|
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
7
7
|
import { AuthModule } from "./auth/auth.module.js";
|
|
8
8
|
{{/if}}
|
|
9
|
+
{{#if hasGraphql}}
|
|
10
|
+
import { GraphqlAppModule } from "./graphql/graphql.module.js";
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if hasTrpc}}
|
|
13
|
+
import { TRPCModule } from "nestjs-trpc";
|
|
14
|
+
import { AppRouterClass as AppRouter } from "./app.router.js";
|
|
15
|
+
import { AppContext } from "./libs/trpc/context.js";
|
|
16
|
+
import { AppErrorHandler } from "./libs/trpc/error.handler.js";
|
|
17
|
+
{{#if hasTrpcAndAuth}}
|
|
18
|
+
import { AuthTRPCMiddleware } from "./libs/middlewares/auth.trpc.middleware.js";
|
|
19
|
+
{{/if}}
|
|
20
|
+
{{/if}}
|
|
9
21
|
|
|
10
22
|
import { AppController } from "./app.controller.js";
|
|
23
|
+
{{#if (and hasTodoExample hasRest)}}
|
|
24
|
+
import { TodoController } from "./api/todo/todo.controller.js";
|
|
25
|
+
{{/if}}
|
|
11
26
|
import { AppService } from "./app.service.js";
|
|
12
27
|
|
|
13
28
|
@Module({
|
|
14
|
-
controllers: [
|
|
29
|
+
controllers: [
|
|
30
|
+
AppController,
|
|
31
|
+
{{#if (and hasTodoExample hasRest)}}
|
|
32
|
+
TodoController,
|
|
33
|
+
{{/if}}
|
|
34
|
+
],
|
|
15
35
|
imports: [
|
|
16
36
|
{{#if (or hasDatabase hasOrm)}}
|
|
17
37
|
DbModule.forRoot({
|
|
@@ -24,7 +44,26 @@ import { AppService } from "./app.service.js";
|
|
|
24
44
|
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
25
45
|
AuthModule,
|
|
26
46
|
{{/if}}
|
|
47
|
+
{{#if hasGraphql}}
|
|
48
|
+
GraphqlAppModule,
|
|
49
|
+
{{/if}}
|
|
50
|
+
{{#if hasTrpc}}
|
|
51
|
+
TRPCModule.forRoot({
|
|
52
|
+
context: AppContext,
|
|
53
|
+
onError: AppErrorHandler,
|
|
54
|
+
}),
|
|
55
|
+
{{/if}}
|
|
56
|
+
],
|
|
57
|
+
providers: [
|
|
58
|
+
AppService,
|
|
59
|
+
{{#if hasTrpc}}
|
|
60
|
+
{{#if hasTrpcAndAuth}}
|
|
61
|
+
AuthTRPCMiddleware,
|
|
62
|
+
{{/if}}
|
|
63
|
+
AppContext,
|
|
64
|
+
AppErrorHandler,
|
|
65
|
+
AppRouter,
|
|
66
|
+
{{/if}}
|
|
27
67
|
],
|
|
28
|
-
providers: [AppService],
|
|
29
68
|
})
|
|
30
69
|
export class AppModule {}
|
|
@@ -2,15 +2,90 @@ import { NestFactory } from "@nestjs/core";
|
|
|
2
2
|
{{#if (eq httpProvider "fastify")}}
|
|
3
3
|
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
|
|
4
4
|
{{/if}}
|
|
5
|
+
import { Logger } from "@nestjs/common";
|
|
5
6
|
import { env } from "@repo/env/api-gateway";
|
|
6
7
|
|
|
7
8
|
import { AppModule } from "./app.module.js";
|
|
9
|
+
{{#if swagger}}
|
|
10
|
+
import { createDocs } from "./docs/create-docs.js";
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if (and swagger useSwaggerScalar)}}
|
|
13
|
+
import { apiReference } from "@scalar/nestjs-api-reference";
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{#if (and swagger (eq useSwaggerScalar false))}}
|
|
16
|
+
import { SwaggerModule } from "@nestjs/swagger";
|
|
17
|
+
{{/if}}
|
|
18
|
+
{{#if (and swagger (or (eq auth "better-auth") (eq auth "better-auth:stateless")))}}
|
|
19
|
+
import { auth } from "./auth/auth.js";
|
|
20
|
+
{{/if}}
|
|
8
21
|
|
|
9
22
|
async function bootstrap() {
|
|
10
23
|
const app = await NestFactory.create{{#if (eq httpProvider "fastify")}}<NestFastifyApplication>(AppModule, new FastifyAdapter()){{else}}(AppModule){{/if}};
|
|
11
24
|
app.enableCors({
|
|
12
25
|
origin: env.CORS_ORIGIN,
|
|
13
26
|
});
|
|
27
|
+
{{#if swagger}}
|
|
28
|
+
if (env.NODE_ENV === "development") {
|
|
29
|
+
const docsPath = "/docs";
|
|
30
|
+
{{#if useSwaggerScalar}}
|
|
31
|
+
app.use(
|
|
32
|
+
docsPath,
|
|
33
|
+
apiReference({
|
|
34
|
+
content: await createDocs(app, {
|
|
35
|
+
title: "{{projectNamePascalCase}} API",
|
|
36
|
+
description: "{{description}}",
|
|
37
|
+
version: "1.0.0",
|
|
38
|
+
integrations: {
|
|
39
|
+
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
40
|
+
betterAuth: {
|
|
41
|
+
auth,
|
|
42
|
+
pathPrefix: "/api/auth",
|
|
43
|
+
},
|
|
44
|
+
{{/if}}
|
|
45
|
+
{{#if (includes apis "trpc")}}
|
|
46
|
+
trpc: {
|
|
47
|
+
routerFilePath: "./src/libs/trpc/@generated/server.ts",
|
|
48
|
+
pathPrefix: "/trpc",
|
|
49
|
+
},
|
|
50
|
+
{{/if}}
|
|
51
|
+
zod: {
|
|
52
|
+
withFastify: {{#if (eq httpProvider "fastify")}}true{{else}}false{{/if}},
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
}),
|
|
56
|
+
pageTitle: "{{projectNamePascalCase}} API Docs",
|
|
57
|
+
theme: "default",
|
|
58
|
+
}),
|
|
59
|
+
);
|
|
60
|
+
{{else}}
|
|
61
|
+
const document = await createDocs(app, {
|
|
62
|
+
title: "{{projectNamePascalCase}} API",
|
|
63
|
+
description: "{{description}}",
|
|
64
|
+
version: "1.0.0",
|
|
65
|
+
integrations: {
|
|
66
|
+
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
67
|
+
betterAuth: {
|
|
68
|
+
auth,
|
|
69
|
+
pathPrefix: "/api/auth",
|
|
70
|
+
},
|
|
71
|
+
{{/if}}
|
|
72
|
+
{{#if (includes apis "trpc")}}
|
|
73
|
+
trpc: {
|
|
74
|
+
routerFilePath: "./src/trpc/router.ts",
|
|
75
|
+
pathPrefix: "/trpc",
|
|
76
|
+
},
|
|
77
|
+
{{/if}}
|
|
78
|
+
zod: {
|
|
79
|
+
withFastify: {{#if (eq httpProvider "fastify")}}true{{else}}false{{/if}},
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
SwaggerModule.setup(docsPath, app, document);
|
|
84
|
+
{{/if}}
|
|
85
|
+
Logger.log(`Swagger documentation available at http://localhost:${env.PORT ?? 3000}${docsPath}`, "SwaggerDocs");
|
|
86
|
+
}
|
|
87
|
+
{{/if}}
|
|
14
88
|
await app.listen(env.PORT ?? 3000);
|
|
89
|
+
Logger.log(`Started backend server on http://localhost:${env.PORT ?? 3000}/api`, "Main");
|
|
15
90
|
}
|
|
16
91
|
await bootstrap();
|