@nest-arch/tui 0.2.7 → 0.4.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 +20 -42
- package/dist/cli.js +1 -1
- package/dist/constants-C3xmDWeK.js +1 -0
- package/dist/index.js +295 -82
- package/dist/templates/base/.env.example.hbs +4 -2
- package/dist/templates/base/.env.hbs +4 -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 +33 -5
- package/dist/templates/base/nest-cli.json.hbs +2 -1
- package/dist/templates/base/pnpm-workspace.yaml.hbs +9 -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 +19 -1
- package/dist/templates/base/src/app.router.ts.hbs +2 -2
- 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 +25 -1
- 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 +7 -4
- 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 +32 -35
- package/dist/templates/base/src/database/db.service.ts.hbs +40 -6
- package/dist/templates/base/src/database/entities/todo.entity.ts.hbs +12 -7
- package/dist/templates/base/src/database/index.ts.hbs +1 -0
- package/dist/templates/base/src/database/orm/drizzle/schema.ts.hbs +47 -5
- package/dist/templates/base/src/database/orm/typeorm/data-source.ts.hbs +12 -4
- package/dist/templates/base/src/libs/trpc/error.handler.ts.hbs +1 -1
- package/dist/templates/base/src/main.ts.hbs +21 -6
- package/dist/templates/base/test/app.e2e-spec.ts.hbs +208 -6
- package/dist/templates/base/test/bootstrap.e2e-spec.ts.hbs +74 -0
- package/dist/templates/base/tsconfig.build.json.hbs +2 -0
- package/dist/templates/base/tsconfig.json.hbs +1 -1
- 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/Dockerfile.hbs +4 -1
- package/dist/templates/extras/swagger/create-docs.ts.hbs +47 -119
- package/dist/templates/feature/graphql/src/graphql/graphql.module.ts.hbs +8 -1
- 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 +4 -3
- package/dist/templates/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +69 -24
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.controller.ts.hbs +3 -1
- 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.service.ts.hbs +98 -32
- package/dist/templates/monorepo/apps/api-gateway/package.json.hbs +0 -1
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.spec.ts.hbs +1 -1
- package/dist/templates/monorepo/apps/api-gateway/test/app.e2e-spec.ts.hbs +20 -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/resolvers/todo.resolver.ts.hbs +24 -21
- package/dist/templates/monorepo/packages/env/src/api-gateway.ts.hbs +9 -3
- package/dist/templates/monorepo/root/.gitignore.hbs +1 -0
- package/dist/templates/monorepo/root/pnpm-workspace.yaml.hbs +9 -0
- 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 +3 -1
- package/dist/templates/single-project/architecture/nest-api/package.json.hbs +0 -1
- package/dist/templates/single-project/architecture/nest-api/src/main.ts.hbs +20 -5
- package/dist/templates/single-project/architecture/nest-microservice/.env.hbs +18 -0
- package/dist/templates/single-project/architecture/nest-microservice/proto/app.proto.hbs +13 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/app.controller.ts.hbs +14 -1
- package/dist/templates/single-project/architecture/nest-microservice/src/app.service.ts.hbs +4 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/main.ts.hbs +13 -2
- package/dist/templates/single-project/architecture/nest-microservice/test/microservice.e2e-spec.ts.hbs +64 -0
- package/dist/templates/single-project/shared/config/env.ts.hbs +27 -3
- package/package.json +7 -4
- package/dist/constants-Cgtoxhmd.js +0 -1
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
{{#if (and hasMongodb useRawSql)}}
|
|
2
|
+
import { BadRequestException, Injectable, NotFoundException } from "@nestjs/common";
|
|
3
|
+
import { ObjectId, type WithId } from "mongodb";
|
|
4
|
+
import { DbService } from "../../database/db.service.js";
|
|
5
|
+
import { CreateTodoDto } from "./dto/create-todo.dto.js";
|
|
6
|
+
import { UpdateTodoDto } from "./dto/update-todo.dto.js";
|
|
7
|
+
interface TodoDocument { title: string; completed: boolean; description?: string; }
|
|
8
|
+
const serialize = ({ _id, ...todo }: WithId<TodoDocument>) => ({ ...todo, id: _id.toHexString() });
|
|
9
|
+
function objectId(id: string): ObjectId {
|
|
10
|
+
if (!/^[a-f0-9]{24}$/iu.test(id)) throw new BadRequestException("Invalid todo identifier");
|
|
11
|
+
return new ObjectId(id);
|
|
12
|
+
}
|
|
13
|
+
@Injectable()
|
|
14
|
+
export class TodoService {
|
|
15
|
+
constructor(private readonly db: DbService) {}
|
|
16
|
+
private get todos() { return this.db.raw.mongo.collection<TodoDocument>("todos"); }
|
|
17
|
+
async findAll() { return (await this.todos.find().sort({ _id: 1 }).limit(100).toArray()).map(serialize); }
|
|
18
|
+
async create(input: CreateTodoDto) {
|
|
19
|
+
const todo = { title: input.title, completed: input.completed ?? false, ...(input.description === undefined ? {} : { description: input.description }) };
|
|
20
|
+
const result = await this.todos.insertOne(todo);
|
|
21
|
+
return { ...todo, id: result.insertedId.toHexString() };
|
|
22
|
+
}
|
|
23
|
+
async update(id: string, input: UpdateTodoDto) {
|
|
24
|
+
const todo = await this.todos.findOneAndUpdate({ _id: objectId(id) }, { $set: input }, { returnDocument: "after" });
|
|
25
|
+
if (!todo) throw new NotFoundException("Todo not found");
|
|
26
|
+
return serialize(todo);
|
|
27
|
+
}
|
|
28
|
+
async delete(id: string) {
|
|
29
|
+
const result = await this.todos.deleteOne({ _id: objectId(id) });
|
|
30
|
+
if (result.deletedCount === 0) throw new NotFoundException("Todo not found");
|
|
31
|
+
return { message: "Todo deleted successfully" };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
{{else}}
|
|
1
35
|
import { Injectable } from "@nestjs/common";
|
|
2
36
|
{{#if hasDatabase}}
|
|
3
37
|
{{#if isMonorepo}}
|
|
@@ -7,8 +41,12 @@ import { DbService } from "../../database/db.service.js";
|
|
|
7
41
|
{{/if}}
|
|
8
42
|
{{#if useDrizzle}}
|
|
9
43
|
import * as schema from "../../database/orm/drizzle/schema.js";
|
|
44
|
+
{{#if hasAuth}}
|
|
45
|
+
import { and, eq } from "drizzle-orm";
|
|
46
|
+
{{else}}
|
|
10
47
|
import { eq } from "drizzle-orm";
|
|
11
48
|
{{/if}}
|
|
49
|
+
{{/if}}
|
|
12
50
|
{{#if useTypeorm}}
|
|
13
51
|
import { Todo } from "../../database/entities/todo.entity.js";
|
|
14
52
|
{{/if}}
|
|
@@ -33,83 +71,109 @@ export class TodoService {
|
|
|
33
71
|
{{#if hasDatabase}}
|
|
34
72
|
{{#if hasAuth}}
|
|
35
73
|
findAll(authorId: string) {
|
|
36
|
-
{{#if
|
|
74
|
+
{{#if isPrisma8}}
|
|
75
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ authorId }).all();
|
|
76
|
+
{{else if usePrisma}}
|
|
37
77
|
return this.db.prisma.todo.findMany({ where: { authorId } });
|
|
38
78
|
{{else if useTypeorm}}
|
|
39
|
-
return this.db.getRepository(Todo).find({ where: { authorId } });
|
|
79
|
+
return this.db.typeorm.getRepository(Todo).find({ where: { authorId } });
|
|
40
80
|
{{else if useDrizzle}}
|
|
41
|
-
return this.db.select().from(schema.todos).where(eq(schema.todos.authorId, authorId));
|
|
81
|
+
return this.db.drizzle.select().from(schema.todos).where(eq(schema.todos.authorId, authorId));
|
|
42
82
|
{{/if}}
|
|
43
83
|
}
|
|
44
84
|
|
|
45
|
-
create(input: CreateTodoDto, authorId: string) {
|
|
46
|
-
{{#if
|
|
47
|
-
return this.db.prisma.
|
|
85
|
+
async create(input: CreateTodoDto, authorId: string) {
|
|
86
|
+
{{#if isPrisma8}}
|
|
87
|
+
return ((this.db.prisma.orm.public as any).Todo).create({ ...input, authorId });
|
|
88
|
+
{{else if usePrisma}}
|
|
89
|
+
const todo = await this.db.prisma.todo.create({ data: { ...input, authorId } });
|
|
90
|
+
return todo;
|
|
48
91
|
{{else if useTypeorm}}
|
|
49
|
-
|
|
92
|
+
const todo = await this.db.typeorm.getRepository(Todo).save(this.db.typeorm.getRepository(Todo).create({ ...input, authorId }));
|
|
93
|
+
return todo;
|
|
50
94
|
{{else if useDrizzle}}
|
|
51
|
-
return this.db.insert(schema.todos).values({ ...input, authorId }).returning();
|
|
95
|
+
return this.db.drizzle.insert(schema.todos).values({ ...input, authorId }).returning();
|
|
52
96
|
{{/if}}
|
|
53
97
|
}
|
|
54
98
|
|
|
55
|
-
update(id: string, input: UpdateTodoDto, authorId: string) {
|
|
56
|
-
{{#if
|
|
57
|
-
return this.db.prisma.
|
|
99
|
+
async update(id: string, input: UpdateTodoDto, authorId: string) {
|
|
100
|
+
{{#if isPrisma8}}
|
|
101
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ authorId, id }).update(input);
|
|
102
|
+
{{else if usePrisma}}
|
|
103
|
+
const result = await this.db.prisma.todo.update({ data: input, where: { authorId, id } });
|
|
104
|
+
return result;
|
|
58
105
|
{{else if useTypeorm}}
|
|
59
|
-
|
|
106
|
+
const result = await this.db.typeorm.getRepository(Todo).update({ authorId, id }, input);
|
|
107
|
+
return result;
|
|
60
108
|
{{else if useDrizzle}}
|
|
61
|
-
return this.db.update(schema.todos).set(input).where(eq(schema.todos.authorId, authorId)
|
|
109
|
+
return this.db.drizzle.update(schema.todos).set(input).where(and(eq(schema.todos.authorId, authorId), eq(schema.todos.id, Number(id)))).returning();
|
|
62
110
|
{{/if}}
|
|
63
111
|
}
|
|
64
112
|
|
|
65
113
|
async delete(id: string, authorId: string) {
|
|
66
|
-
{{#if
|
|
114
|
+
{{#if isPrisma8}}
|
|
115
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ authorId, id }).delete();
|
|
116
|
+
{{else if usePrisma}}
|
|
67
117
|
await this.db.prisma.todo.delete({ where: { authorId, id } });
|
|
68
118
|
{{else if useTypeorm}}
|
|
69
|
-
await this.db.getRepository(Todo).delete({ authorId, id });
|
|
119
|
+
await this.db.typeorm.getRepository(Todo).delete({ authorId, id });
|
|
70
120
|
{{else if useDrizzle}}
|
|
71
|
-
await this.db.delete(schema.todos).where(eq(schema.todos.authorId, authorId)
|
|
121
|
+
await this.db.drizzle.delete(schema.todos).where(and(eq(schema.todos.authorId, authorId), eq(schema.todos.id, Number(id))));
|
|
72
122
|
{{/if}}
|
|
73
123
|
return { message: "Todo deleted successfully" };
|
|
74
124
|
}
|
|
75
125
|
{{else}}
|
|
76
126
|
findAll() {
|
|
77
|
-
{{#if
|
|
127
|
+
{{#if isPrisma8}}
|
|
128
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
129
|
+
{{else if usePrisma}}
|
|
78
130
|
return this.db.prisma.todo.findMany();
|
|
79
131
|
{{else if useTypeorm}}
|
|
80
|
-
return this.db.getRepository(Todo).find();
|
|
132
|
+
return this.db.typeorm.getRepository(Todo).find();
|
|
81
133
|
{{else if useDrizzle}}
|
|
82
|
-
return this.db.select().from(schema.todos);
|
|
134
|
+
return this.db.drizzle.select().from(schema.todos);
|
|
83
135
|
{{/if}}
|
|
84
136
|
}
|
|
85
137
|
|
|
86
|
-
create(input: CreateTodoDto) {
|
|
87
|
-
{{#if
|
|
88
|
-
return this.db.prisma.
|
|
138
|
+
async create(input: CreateTodoDto) {
|
|
139
|
+
{{#if isPrisma8}}
|
|
140
|
+
return ((this.db.prisma.orm.public as any).Todo).create(input);
|
|
141
|
+
{{else if usePrisma}}
|
|
142
|
+
const todo = await this.db.prisma.todo.create({ data: input });
|
|
143
|
+
return todo;
|
|
89
144
|
{{else if useTypeorm}}
|
|
90
|
-
|
|
145
|
+
const todo = await this.db.typeorm.getRepository(Todo).save(this.db.typeorm.getRepository(Todo).create(input));
|
|
146
|
+
return todo;
|
|
91
147
|
{{else if useDrizzle}}
|
|
92
|
-
|
|
148
|
+
const [todo] = await this.db.drizzle.insert(schema.todos).values(input).returning();
|
|
149
|
+
return todo;
|
|
93
150
|
{{/if}}
|
|
94
151
|
}
|
|
95
152
|
|
|
96
|
-
update(id: string, input: UpdateTodoDto) {
|
|
97
|
-
{{#if
|
|
98
|
-
return this.db.prisma.
|
|
153
|
+
async update(id: string, input: UpdateTodoDto) {
|
|
154
|
+
{{#if isPrisma8}}
|
|
155
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(input);
|
|
156
|
+
{{else if usePrisma}}
|
|
157
|
+
const result = await this.db.prisma.todo.update({ data: input, where: { id } });
|
|
158
|
+
return result;
|
|
99
159
|
{{else if useTypeorm}}
|
|
100
|
-
|
|
160
|
+
const result = await this.db.typeorm.getRepository(Todo).update(id, input);
|
|
161
|
+
return result;
|
|
101
162
|
{{else if useDrizzle}}
|
|
102
|
-
|
|
163
|
+
const [todo] = await this.db.drizzle.update(schema.todos).set(input).where(eq(schema.todos.id, Number(id))).returning();
|
|
164
|
+
return todo;
|
|
103
165
|
{{/if}}
|
|
104
166
|
}
|
|
105
167
|
|
|
106
168
|
async delete(id: string) {
|
|
107
|
-
{{#if
|
|
169
|
+
{{#if isPrisma8}}
|
|
170
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ id }).delete();
|
|
171
|
+
{{else if usePrisma}}
|
|
108
172
|
await this.db.prisma.todo.delete({ where: { id } });
|
|
109
173
|
{{else if useTypeorm}}
|
|
110
|
-
await this.db.getRepository(Todo).delete(id);
|
|
174
|
+
await this.db.typeorm.getRepository(Todo).delete(id);
|
|
111
175
|
{{else if useDrizzle}}
|
|
112
|
-
await this.db.delete(schema.todos).where(eq(schema.todos.id, id));
|
|
176
|
+
await this.db.drizzle.delete(schema.todos).where(eq(schema.todos.id, Number(id)));
|
|
113
177
|
{{/if}}
|
|
114
178
|
return { message: "Todo deleted successfully" };
|
|
115
179
|
}
|
|
@@ -143,3 +207,5 @@ export class TodoService {
|
|
|
143
207
|
}
|
|
144
208
|
{{/if}}
|
|
145
209
|
}
|
|
210
|
+
|
|
211
|
+
{{/if}}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// oxlint-disable vitest/require-mock-type-parameters
|
|
2
2
|
import type { TestingModule } from "@nestjs/testing";
|
|
3
3
|
import { Test } from "@nestjs/testing";
|
|
4
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { beforeEach, describe, expect, it{{#if (or hasDatabase hasOrm)}}, vi{{/if}} } from "vitest";
|
|
5
5
|
|
|
6
6
|
import { AppController } from "./app.controller.js";
|
|
7
7
|
import { AppService } from "./app.service.js";
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { INestApplication } from "@nestjs/common";
|
|
2
2
|
import { Test, TestingModule } from "@nestjs/testing";
|
|
3
|
+
{{#if (eq httpProvider "fastify")}}
|
|
4
|
+
import { FastifyAdapter } from "@nestjs/platform-fastify";
|
|
5
|
+
{{/if}}
|
|
3
6
|
import request from "supertest";
|
|
7
|
+
import { afterEach, beforeEach, describe, it } from "vitest";
|
|
4
8
|
import type { App } from "supertest/types";
|
|
5
9
|
|
|
6
10
|
import { AppModule } from "./../src/app.module.js";
|
|
@@ -13,15 +17,30 @@ describe("AppController (e2e)", () => {
|
|
|
13
17
|
imports: [AppModule],
|
|
14
18
|
}).compile();
|
|
15
19
|
|
|
20
|
+
{{#if (eq httpProvider "fastify")}}
|
|
21
|
+
app = moduleFixture.createNestApplication(new FastifyAdapter());
|
|
22
|
+
{{else}}
|
|
16
23
|
app = moduleFixture.createNestApplication();
|
|
24
|
+
{{/if}}
|
|
17
25
|
await app.init();
|
|
26
|
+
{{#if (eq httpProvider "fastify")}}
|
|
27
|
+
await app.getHttpAdapter().getInstance().ready();
|
|
28
|
+
{{/if}}
|
|
18
29
|
});
|
|
19
30
|
|
|
20
31
|
it("/ (GET)", () => {
|
|
21
32
|
return request(app.getHttpServer()).get("/").expect(200).expect("Hello World!");
|
|
22
33
|
});
|
|
23
34
|
|
|
35
|
+
it("returns 404 for an unknown route", async () => {
|
|
36
|
+
await request(app.getHttpServer()).get("/__missing_route__").expect(404);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it("rejects unsupported methods", async () => {
|
|
40
|
+
await request(app.getHttpServer()).post("/").send({ unexpected: true }).expect(404);
|
|
41
|
+
});
|
|
42
|
+
|
|
24
43
|
afterEach(async () => {
|
|
25
|
-
await app
|
|
44
|
+
await app?.close();
|
|
26
45
|
});
|
|
27
46
|
});
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
import { UseGuards } from "@nestjs/common";
|
|
3
3
|
{{/if}}
|
|
4
4
|
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
5
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
6
|
+
import { UserEntity } from "../../auth/decorators/index.js";
|
|
7
|
+
import { GqlAuthGuard } from "../../auth/guards/gql-auth.guard.js";
|
|
8
|
+
{{/if}}
|
|
9
|
+
import { DbService } from "@repo/db";
|
|
5
10
|
import { CreateTodoInput } from "../dto/create-todo.input.js";
|
|
6
11
|
import { UpdateTodoInput } from "../dto/update-todo.input.js";
|
|
7
|
-
import { DbService } from "@repo/db";
|
|
8
12
|
{{#if useTypeorm}}
|
|
9
13
|
import { GraphRelationBuilder } from "typeorm-relations-graphql";
|
|
10
14
|
import { GraphQLResolveInfo } from "graphql";
|
|
@@ -14,11 +18,9 @@ import * as schema from "@repo/db/src/orm/drizzle/schema.js";
|
|
|
14
18
|
{{/if}}
|
|
15
19
|
{{#if (and hasAuth hasDatabase)}}
|
|
16
20
|
import { Todo } from "../models/todo.model.js";
|
|
17
|
-
import { UserEntity } from "../../auth/decorators/index.js";
|
|
18
|
-
import { GqlAuthGuard } from "../../auth/guards/gql-auth.guard.js";
|
|
19
21
|
{{/if}}
|
|
20
22
|
|
|
21
|
-
@Resolver(
|
|
23
|
+
@Resolver(() => Todo)
|
|
22
24
|
export class TodoResolver {
|
|
23
25
|
constructor(private readonly db: DbService) {}
|
|
24
26
|
|
|
@@ -28,11 +30,13 @@ export class TodoResolver {
|
|
|
28
30
|
}{{#if hasDatabase}}
|
|
29
31
|
|
|
30
32
|
@Query(() => [Todo])
|
|
31
|
-
todos({{#if useTypeorm}}info: GraphQLResolveInfo{{/if}})
|
|
33
|
+
todos({{#if useTypeorm}}info: GraphQLResolveInfo{{/if}}) {
|
|
32
34
|
{{#if useTypeorm}}
|
|
33
35
|
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
34
36
|
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
35
37
|
return this.db.getRepository(Todo).find({ relations });
|
|
38
|
+
{{else if isPrisma8}}
|
|
39
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
36
40
|
{{else if usePrisma}}
|
|
37
41
|
return this.db.prisma.todo.findMany();
|
|
38
42
|
{{else if useDrizzle}}
|
|
@@ -42,14 +46,12 @@ export class TodoResolver {
|
|
|
42
46
|
{{/if}}
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
@Mutation(() => Todo)
|
|
46
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
47
49
|
@UseGuards(GqlAuthGuard)
|
|
48
|
-
|
|
50
|
+
@Mutation(() => Todo)
|
|
49
51
|
createTodo(
|
|
50
|
-
@
|
|
51
|
-
@
|
|
52
|
-
)
|
|
52
|
+
@UserEntity() user: { id: string },
|
|
53
|
+
@Args("input") input: CreateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
54
|
+
) {
|
|
53
55
|
{{#if useTypeorm}}
|
|
54
56
|
const entity = this.db.getRepository(Todo).create(input);
|
|
55
57
|
const saved = await this.db.getRepository(Todo).save(entity);
|
|
@@ -59,9 +61,11 @@ export class TodoResolver {
|
|
|
59
61
|
where: { id: saved.id },
|
|
60
62
|
relations,
|
|
61
63
|
});
|
|
64
|
+
{{else if isPrisma8}}
|
|
65
|
+
return ((this.db.prisma.orm.public as any).Todo).create({ ...input, authorId: user.id });
|
|
62
66
|
{{else if usePrisma}}
|
|
63
67
|
return this.db.prisma.todo.create({
|
|
64
|
-
data: { ...input
|
|
68
|
+
data: { ...input, authorId: user.id },
|
|
65
69
|
});
|
|
66
70
|
{{else if useDrizzle}}
|
|
67
71
|
const [todo] = await this.db.insert(schema.todos).values(input).returning();
|
|
@@ -71,13 +75,9 @@ export class TodoResolver {
|
|
|
71
75
|
{{/if}}
|
|
72
76
|
}
|
|
73
77
|
|
|
74
|
-
@Mutation(() => Todo)
|
|
75
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
76
78
|
@UseGuards(GqlAuthGuard)
|
|
77
|
-
|
|
78
|
-
updateTodo(
|
|
79
|
-
@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
80
|
-
): Promise<Todo> {
|
|
79
|
+
@Mutation(() => Todo)
|
|
80
|
+
updateTodo(@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}) {
|
|
81
81
|
const { id, ...data } = input;
|
|
82
82
|
{{#if useTypeorm}}
|
|
83
83
|
await this.db.getRepository(Todo).update(id, data);
|
|
@@ -87,6 +87,8 @@ export class TodoResolver {
|
|
|
87
87
|
where: { id },
|
|
88
88
|
relations,
|
|
89
89
|
});
|
|
90
|
+
{{else if isPrisma8}}
|
|
91
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(data);
|
|
90
92
|
{{else if usePrisma}}
|
|
91
93
|
return this.db.prisma.todo.update({ where: { id }, data });
|
|
92
94
|
{{else if useDrizzle}}
|
|
@@ -101,14 +103,15 @@ export class TodoResolver {
|
|
|
101
103
|
{{/if}}
|
|
102
104
|
}
|
|
103
105
|
|
|
104
|
-
@Mutation(() => Boolean)
|
|
105
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
106
106
|
@UseGuards(GqlAuthGuard)
|
|
107
|
-
|
|
107
|
+
@Mutation(() => Boolean)
|
|
108
108
|
async deleteTodo(@Args("id") id: string): Promise<boolean> {
|
|
109
109
|
{{#if useTypeorm}}
|
|
110
110
|
const result = await this.db.getRepository(Todo).delete(id);
|
|
111
111
|
return (result.affected ?? 0) > 0;
|
|
112
|
+
{{else if isPrisma8}}
|
|
113
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ id }).delete();
|
|
114
|
+
return true;
|
|
112
115
|
{{else if usePrisma}}
|
|
113
116
|
await this.db.prisma.todo.delete({ where: { id } });
|
|
114
117
|
return true;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "dotenv/config";
|
|
2
2
|
import { createEnv } from "@t3-oss/env-core";
|
|
3
|
-
import
|
|
3
|
+
import { z } from "zod";
|
|
4
4
|
|
|
5
5
|
export const env = createEnv({
|
|
6
6
|
/**
|
|
@@ -31,7 +31,7 @@ export const env = createEnv({
|
|
|
31
31
|
.default("development"),
|
|
32
32
|
PORT: z
|
|
33
33
|
.string()
|
|
34
|
-
.transform(
|
|
34
|
+
.transform(Number)
|
|
35
35
|
.default(3000),
|
|
36
36
|
{{#if hasPostgres}}
|
|
37
37
|
POSTGRES_URL: z.url(),
|
|
@@ -51,9 +51,15 @@ export const env = createEnv({
|
|
|
51
51
|
.transform((val) => val === "true")
|
|
52
52
|
.default(true),
|
|
53
53
|
{{/if}}
|
|
54
|
-
{{#if (
|
|
54
|
+
{{#if (eq auth "passport")}}
|
|
55
55
|
JWT_ACCESS_SECRET: z.string().min(32),
|
|
56
|
+
{{#if hasDatabase}}
|
|
56
57
|
JWT_REFRESH_SECRET: z.string().min(32),
|
|
57
58
|
{{/if}}
|
|
59
|
+
{{/if}}
|
|
60
|
+
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
61
|
+
BETTER_AUTH_SECRET: z.string().min(32),
|
|
62
|
+
BETTER_AUTH_URL: z.url(),
|
|
63
|
+
{{/if}}
|
|
58
64
|
},
|
|
59
65
|
});
|
|
@@ -2,6 +2,10 @@ packages:
|
|
|
2
2
|
- apps/*
|
|
3
3
|
- packages/*
|
|
4
4
|
allowBuilds:
|
|
5
|
+
{{#if useDrizzle}}
|
|
6
|
+
esbuild: true
|
|
7
|
+
{{/if}}
|
|
8
|
+
protobufjs: true
|
|
5
9
|
'@nestjs/core': true
|
|
6
10
|
esbuild: true
|
|
7
11
|
{{#if swagger}}
|
|
@@ -16,6 +20,11 @@ allowBuilds:
|
|
|
16
20
|
{{#if hasSqlite}}
|
|
17
21
|
better-sqlite3: true
|
|
18
22
|
{{/if}}
|
|
23
|
+
{{#if isPrisma8}}
|
|
24
|
+
esbuild: true
|
|
25
|
+
msgpackr-extract: true
|
|
26
|
+
workerd: true
|
|
27
|
+
{{/if}}
|
|
19
28
|
catalog:
|
|
20
29
|
"@types/node": ^22.13.14
|
|
21
30
|
dotenv: ^17.2.2
|
|
@@ -16,10 +16,12 @@ SQLITE_PATH=file:./src/database/dev.db
|
|
|
16
16
|
{{#if hasMongodb}}
|
|
17
17
|
MONGODB_URL=mongodb://localhost:27017/{{projectNameKebab}}_db
|
|
18
18
|
{{/if}}
|
|
19
|
-
{{#if (
|
|
19
|
+
{{#if (eq auth "passport")}}
|
|
20
20
|
JWT_ACCESS_SECRET=change-me-to-a-random-secret-at-least-32-characters-long
|
|
21
|
+
{{#if hasDatabase}}
|
|
21
22
|
JWT_REFRESH_SECRET=change-me-to-a-different-random-secret-at-least-32-characters
|
|
22
23
|
{{/if}}
|
|
24
|
+
{{/if}}
|
|
23
25
|
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
24
26
|
BETTER_AUTH_SECRET=change-me-to-a-random-secret-at-least-32-characters-long
|
|
25
27
|
BETTER_AUTH_URL=http://localhost:3000
|
|
@@ -2,10 +2,18 @@ import { NestFactory } from "@nestjs/core";
|
|
|
2
2
|
{{#if (eq httpProvider "fastify")}}
|
|
3
3
|
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
|
|
4
4
|
{{/if}}
|
|
5
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
6
|
+
import { Logger } from "@nestjs/common";
|
|
7
|
+
import { ZodValidationPipe } from "nestjs-zod";
|
|
8
|
+
{{else}}
|
|
5
9
|
import { Logger, StandardSchemaValidationPipe } from "@nestjs/common";
|
|
10
|
+
{{/if}}
|
|
6
11
|
|
|
7
12
|
import { AppModule } from "./app.module.js";
|
|
8
13
|
import { env } from "./config/env.js";
|
|
14
|
+
{{#if isPrisma8}}
|
|
15
|
+
import { connectDatabase } from "./prisma/db.js";
|
|
16
|
+
{{/if}}
|
|
9
17
|
{{#if swagger}}
|
|
10
18
|
import { createDocs } from "./docs/create-docs.js";
|
|
11
19
|
{{/if}}
|
|
@@ -20,6 +28,9 @@ import { auth } from "./auth/auth.js";
|
|
|
20
28
|
{{/if}}
|
|
21
29
|
|
|
22
30
|
async function bootstrap() {
|
|
31
|
+
{{#if isPrisma8}}
|
|
32
|
+
await connectDatabase();
|
|
33
|
+
{{/if}}
|
|
23
34
|
const app = await NestFactory.create{{#if (eq httpProvider "fastify")}}<NestFastifyApplication>(AppModule, new FastifyAdapter()){{else}}(AppModule){{/if}};
|
|
24
35
|
app.enableCors({
|
|
25
36
|
origin: env.CORS_ORIGIN,
|
|
@@ -27,7 +38,11 @@ async function bootstrap() {
|
|
|
27
38
|
{{#if hasRest}}
|
|
28
39
|
app.setGlobalPrefix("api");
|
|
29
40
|
{{/if}}
|
|
41
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
42
|
+
app.useGlobalPipes(new ZodValidationPipe());
|
|
43
|
+
{{else}}
|
|
30
44
|
app.useGlobalPipes(new StandardSchemaValidationPipe());
|
|
45
|
+
{{/if}}
|
|
31
46
|
app.enableShutdownHooks();
|
|
32
47
|
{{#if swagger}}
|
|
33
48
|
if (env.NODE_ENV === "development") {
|
|
@@ -87,17 +102,17 @@ async function bootstrap() {
|
|
|
87
102
|
});
|
|
88
103
|
SwaggerModule.setup(docsPath, app, document);
|
|
89
104
|
{{/if}}
|
|
90
|
-
Logger.log(`Swagger documentation available at http://localhost:${env.PORT
|
|
105
|
+
Logger.log(`Swagger documentation available at http://localhost:${env.PORT}${docsPath}`, "SwaggerDocs");
|
|
91
106
|
}
|
|
92
107
|
{{/if}}
|
|
93
108
|
|
|
94
|
-
await app.listen(env.PORT
|
|
109
|
+
await app.listen(env.PORT);
|
|
95
110
|
{{#if hasRest}}
|
|
96
|
-
Logger.log(`Started backend server on http://localhost:${env.PORT
|
|
111
|
+
Logger.log(`Started backend server on http://localhost:${env.PORT}/api`, "Main");
|
|
97
112
|
{{else if hasTrpc}}
|
|
98
|
-
Logger.log(`Started trpc server on http://localhost:${env.PORT
|
|
113
|
+
Logger.log(`Started trpc server on http://localhost:${env.PORT}/trpc`, "Main");
|
|
99
114
|
{{else}}
|
|
100
|
-
Logger.log(`Started server on http://localhost:${env.PORT
|
|
115
|
+
Logger.log(`Started server on http://localhost:${env.PORT}`, "Main");
|
|
101
116
|
{{/if}}
|
|
102
117
|
}
|
|
103
118
|
await bootstrap();
|
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
PORT=3000
|
|
2
2
|
MICROSERVICE_PORT=3001
|
|
3
3
|
CORS_ORIGIN=http://localhost:3001
|
|
4
|
+
{{#if (includes microservices "redis")}}
|
|
5
|
+
REDIS_URL=redis://127.0.0.1:6379
|
|
6
|
+
{{/if}}
|
|
7
|
+
{{#if (includes microservices "mqtt")}}
|
|
8
|
+
MQTT_URL=mqtt://127.0.0.1:1883
|
|
9
|
+
{{/if}}
|
|
10
|
+
{{#if (includes microservices "nats")}}
|
|
11
|
+
NATS_URL=nats://127.0.0.1:4222
|
|
12
|
+
{{/if}}
|
|
13
|
+
{{#if (includes microservices "rabbitmq")}}
|
|
14
|
+
RABBITMQ_URL=amqp://127.0.0.1:5672
|
|
15
|
+
{{/if}}
|
|
16
|
+
{{#if (includes microservices "kafka")}}
|
|
17
|
+
KAFKA_BROKER=127.0.0.1:9092
|
|
18
|
+
{{/if}}
|
|
19
|
+
{{#if (includes microservices "grpc")}}
|
|
20
|
+
GRPC_URL=0.0.0.0:5000
|
|
21
|
+
{{/if}}
|
|
4
22
|
{{#if hasGraphql}}
|
|
5
23
|
GRAPHQL_PLAYGROUND=true
|
|
6
24
|
{{/if}}
|
package/dist/templates/single-project/architecture/nest-microservice/src/app.controller.ts.hbs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Controller,
|
|
1
|
+
import { Controller, Get } from "@nestjs/common";
|
|
2
|
+
import { EventPattern, {{#if (includes microservices "grpc")}}GrpcMethod{{else}}MessagePattern{{/if}} } from "@nestjs/microservices";
|
|
2
3
|
|
|
3
4
|
import { AppService } from "./app.service.js";
|
|
4
5
|
|
|
@@ -6,10 +7,22 @@ import { AppService } from "./app.service.js";
|
|
|
6
7
|
export class AppController {
|
|
7
8
|
constructor(private readonly appService: AppService) {}
|
|
8
9
|
|
|
10
|
+
@Get()
|
|
11
|
+
getHello(): string {
|
|
12
|
+
return this.appService.getHello();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
{{#if (includes microservices "grpc")}}
|
|
16
|
+
@GrpcMethod("AppService", "Ping")
|
|
17
|
+
handleGrpcPing(): { message: string } {
|
|
18
|
+
return { message: this.appService.handlePing() };
|
|
19
|
+
}
|
|
20
|
+
{{else}}
|
|
9
21
|
@MessagePattern("ping")
|
|
10
22
|
handlePing(): string {
|
|
11
23
|
return this.appService.handlePing();
|
|
12
24
|
}
|
|
25
|
+
{{/if}}
|
|
13
26
|
|
|
14
27
|
@EventPattern("log")
|
|
15
28
|
handleLog(data: Record<string, unknown>): void {
|