@nest-arch/tui 0.2.8 → 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 +297 -84
- 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 +8 -4
- 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/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 +4 -19
- 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 +51 -0
- 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 +9 -0
- 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 +5 -2
- package/dist/constants-Cgtoxhmd.js +0 -1
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { defineConfig } from "vitest/config";
|
|
2
|
-
import tsconfigPaths from "vite-tsconfig-paths";
|
|
3
2
|
|
|
4
3
|
export default defineConfig({
|
|
5
|
-
|
|
4
|
+
resolve: {
|
|
5
|
+
tsconfigPaths: true,
|
|
6
|
+
},
|
|
6
7
|
test: {
|
|
8
|
+
include: ["**/*.spec.ts"],
|
|
7
9
|
globals: true,
|
|
8
10
|
root: "./",
|
|
9
|
-
include: ["**/*.spec.ts"],
|
|
10
11
|
},
|
|
11
12
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# This lockfile marks the generated application as an independent Yarn project.
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// @ts-nocheck
|
|
2
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access, import/no-unresolved */
|
|
3
|
-
/* oxlint-disable import/no-unresolved */
|
|
4
|
-
// oxlint-disable no-unused-vars
|
|
5
1
|
|
|
6
2
|
import type { INestApplication } from "@nestjs/common";
|
|
7
3
|
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
|
|
@@ -80,7 +76,8 @@ async function applyZodCleanup(
|
|
|
80
76
|
options?: NonNullable<DocsIntegrations["zod"]>
|
|
81
77
|
) {
|
|
82
78
|
try {
|
|
83
|
-
const
|
|
79
|
+
const packageName = "nestjs-zod";
|
|
80
|
+
const { cleanupOpenApiDoc } = await import(packageName);
|
|
84
81
|
if (typeof cleanupOpenApiDoc !== "function") {
|
|
85
82
|
return baseSpec;
|
|
86
83
|
}
|
|
@@ -143,7 +140,8 @@ async function applyTrpcSpec(options?: NonNullable<DocsIntegrations["trpc"]>) {
|
|
|
143
140
|
}
|
|
144
141
|
|
|
145
142
|
try {
|
|
146
|
-
const
|
|
143
|
+
const packageName = "@trpc/openapi";
|
|
144
|
+
const { generateOpenAPIDocument } = await import(packageName);
|
|
147
145
|
|
|
148
146
|
if (typeof generateOpenAPIDocument !== "function") {
|
|
149
147
|
return null;
|
|
@@ -174,19 +172,6 @@ async function applyTrpcSpec(options?: NonNullable<DocsIntegrations["trpc"]>) {
|
|
|
174
172
|
}
|
|
175
173
|
}
|
|
176
174
|
|
|
177
|
-
function createEmptyBaseSpec(options: CreateDocsOptions): OpenAPIObject {
|
|
178
|
-
return {
|
|
179
|
-
info: {
|
|
180
|
-
description: options.description ?? "Generated with Nest Arch",
|
|
181
|
-
title: options.title ?? "NestJS API",
|
|
182
|
-
version: options.version ?? "1.0.0",
|
|
183
|
-
},
|
|
184
|
-
openapi: "3.1.0",
|
|
185
|
-
paths: {},
|
|
186
|
-
tags: [],
|
|
187
|
-
} as OpenAPIObject;
|
|
188
|
-
}
|
|
189
|
-
|
|
190
175
|
export async function createDocs(
|
|
191
176
|
app: INestApplication,
|
|
192
177
|
options: CreateDocsOptions = {}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Module } from "@nestjs/common";
|
|
2
|
-
import { GraphQLModule } from "@nestjs/graphql";
|
|
2
|
+
import { Query, Resolver, GraphQLModule } from "@nestjs/graphql";
|
|
3
3
|
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";
|
|
4
4
|
import { join } from "path";
|
|
5
5
|
import { env } from "../config/env.js";
|
|
@@ -12,6 +12,12 @@ import { env } from "../config/env.js";
|
|
|
12
12
|
import { TodoResolver } from "./resolvers/todo.resolver.js";
|
|
13
13
|
{{/if}}
|
|
14
14
|
|
|
15
|
+
@Resolver()
|
|
16
|
+
class HealthResolver {
|
|
17
|
+
@Query(() => String)
|
|
18
|
+
hello(): string { return "Hello GraphQL!"; }
|
|
19
|
+
}
|
|
20
|
+
|
|
15
21
|
@Module({
|
|
16
22
|
imports: [
|
|
17
23
|
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
@@ -25,6 +31,7 @@ import { TodoResolver } from "./resolvers/todo.resolver.js";
|
|
|
25
31
|
}),
|
|
26
32
|
],
|
|
27
33
|
providers: [
|
|
34
|
+
HealthResolver,
|
|
28
35
|
{{#if hasTodoExample}}
|
|
29
36
|
TodoResolver,
|
|
30
37
|
{{/if}}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Field, ID, ObjectType } from "@nestjs/graphql";
|
|
2
2
|
|
|
3
3
|
import { BaseModel } from "./base.model.js";
|
|
4
|
+
{{#if hasAuth}}
|
|
4
5
|
// oxlint-disable-next-line import/no-cycle
|
|
5
6
|
import { User } from "./user.model.js";
|
|
7
|
+
{{/if}}
|
|
6
8
|
|
|
7
9
|
@ObjectType()
|
|
8
10
|
export class Todo extends BaseModel {
|
|
@@ -15,9 +17,11 @@ export class Todo extends BaseModel {
|
|
|
15
17
|
@Field()
|
|
16
18
|
completed: boolean;
|
|
17
19
|
|
|
20
|
+
{{#if hasAuth}}
|
|
18
21
|
@Field(() => ID, { nullable: true })
|
|
19
22
|
authorId: string | null;
|
|
20
23
|
|
|
21
24
|
@Field(() => User, { nullable: true })
|
|
22
25
|
author: User | null;
|
|
26
|
+
{{/if}}
|
|
23
27
|
}
|
package/dist/templates/feature/graphql/src/graphql/orm/drizzle/drizzle-graphql.module.ts.hbs
CHANGED
|
@@ -3,6 +3,7 @@ import { buildSchema } from "drizzle-graphql";
|
|
|
3
3
|
{{#if isMonorepo}}
|
|
4
4
|
import { db } from "@repo/db";
|
|
5
5
|
{{else}}
|
|
6
|
+
import { env } from "../../../config/env.js";
|
|
6
7
|
{{#if hasPostgres}}
|
|
7
8
|
import { drizzle } from "drizzle-orm/node-postgres";
|
|
8
9
|
import { Pool } from "pg";
|
|
@@ -20,13 +21,13 @@ import * as dbSchema from "../database/orm/drizzle/schema.js";
|
|
|
20
21
|
|
|
21
22
|
const schema = buildSchema({{#if isMonorepo}}db{{else}}
|
|
22
23
|
{{#if hasPostgres}}
|
|
23
|
-
drizzle(new Pool({ connectionString:
|
|
24
|
+
drizzle(new Pool({ connectionString: env.POSTGRES_URL }), { schema: dbSchema })
|
|
24
25
|
{{/if}}
|
|
25
26
|
{{#if hasMysql}}
|
|
26
|
-
drizzle(mysql.createPool(
|
|
27
|
+
drizzle(mysql.createPool(env.MYSQL_URL), { schema: dbSchema })
|
|
27
28
|
{{/if}}
|
|
28
29
|
{{#if hasSqlite}}
|
|
29
|
-
drizzle(new Database(
|
|
30
|
+
drizzle(new Database(env.SQLITE_PATH), { schema: dbSchema })
|
|
30
31
|
{{/if}}
|
|
31
32
|
{{/if}});
|
|
32
33
|
|
|
@@ -1,3 +1,43 @@
|
|
|
1
|
+
{{#if (and usePrisma (eq auth "none"))}}
|
|
2
|
+
import { BadRequestException, NotFoundException } from "@nestjs/common";
|
|
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}}
|
|
1
41
|
{{#if (and hasAuth hasDatabase)}}
|
|
2
42
|
import { UseGuards } from "@nestjs/common";
|
|
3
43
|
{{/if}}
|
|
@@ -39,6 +79,8 @@ export class TodoResolver {
|
|
|
39
79
|
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
40
80
|
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
41
81
|
return this.db.getRepository(Todo).find({ relations });
|
|
82
|
+
{{else if isPrisma8}}
|
|
83
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
42
84
|
{{else if usePrisma}}
|
|
43
85
|
return this.db.prisma.todo.findMany();
|
|
44
86
|
{{else if useDrizzle}}
|
|
@@ -63,6 +105,8 @@ export class TodoResolver {
|
|
|
63
105
|
where: { id: saved.id },
|
|
64
106
|
relations,
|
|
65
107
|
});
|
|
108
|
+
{{else if isPrisma8}}
|
|
109
|
+
return ((this.db.prisma.orm.public as any).Todo).create({ ...input, authorId: user.id });
|
|
66
110
|
{{else if usePrisma}}
|
|
67
111
|
return this.db.prisma.todo.create({
|
|
68
112
|
data: { ...input, authorId: user.id },
|
|
@@ -87,6 +131,8 @@ export class TodoResolver {
|
|
|
87
131
|
where: { id },
|
|
88
132
|
relations,
|
|
89
133
|
});
|
|
134
|
+
{{else if isPrisma8}}
|
|
135
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(data);
|
|
90
136
|
{{else if usePrisma}}
|
|
91
137
|
return this.db.prisma.todo.update({ where: { id }, data });
|
|
92
138
|
{{else if useDrizzle}}
|
|
@@ -107,6 +153,9 @@ export class TodoResolver {
|
|
|
107
153
|
{{#if useTypeorm}}
|
|
108
154
|
const result = await this.db.getRepository(Todo).delete(id);
|
|
109
155
|
return (result.affected ?? 0) > 0;
|
|
156
|
+
{{else if isPrisma8}}
|
|
157
|
+
await ((this.db.prisma.orm.public as any).Todo).where({ id }).delete();
|
|
158
|
+
return true;
|
|
110
159
|
{{else if usePrisma}}
|
|
111
160
|
await this.db.prisma.todo.delete({ where: { id } });
|
|
112
161
|
return true;
|
|
@@ -118,3 +167,5 @@ export class TodoResolver {
|
|
|
118
167
|
{{/if}}
|
|
119
168
|
}{{/if}}
|
|
120
169
|
}
|
|
170
|
+
|
|
171
|
+
{{/if}}
|
|
@@ -16,7 +16,9 @@ import {
|
|
|
16
16
|
ApiOkResponse,
|
|
17
17
|
ApiOperation,
|
|
18
18
|
ApiTags,
|
|
19
|
+
{{#if (or isPassportAuth isBetterAuth)}}
|
|
19
20
|
ApiUnauthorizedResponse,
|
|
21
|
+
{{/if}}
|
|
20
22
|
} from "@nestjs/swagger";
|
|
21
23
|
{{/if}}
|
|
22
24
|
{{#if isPassportAuth}}
|
|
@@ -164,7 +166,7 @@ export class TodoController {
|
|
|
164
166
|
return this.todoService.delete(id, session.user.id);
|
|
165
167
|
}
|
|
166
168
|
{{else}}
|
|
167
|
-
|
|
169
|
+
delete(@Param("id") id: string) {
|
|
168
170
|
return this.todoService.delete(id);
|
|
169
171
|
}
|
|
170
172
|
{{/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,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
|
});
|
|
@@ -35,6 +35,8 @@ export class TodoResolver {
|
|
|
35
35
|
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
36
36
|
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
37
37
|
return this.db.getRepository(Todo).find({ relations });
|
|
38
|
+
{{else if isPrisma8}}
|
|
39
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
38
40
|
{{else if usePrisma}}
|
|
39
41
|
return this.db.prisma.todo.findMany();
|
|
40
42
|
{{else if useDrizzle}}
|
|
@@ -59,6 +61,8 @@ 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
68
|
data: { ...input, authorId: user.id },
|
|
@@ -83,6 +87,8 @@ export class TodoResolver {
|
|
|
83
87
|
where: { id },
|
|
84
88
|
relations,
|
|
85
89
|
});
|
|
90
|
+
{{else if isPrisma8}}
|
|
91
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(data);
|
|
86
92
|
{{else if usePrisma}}
|
|
87
93
|
return this.db.prisma.todo.update({ where: { id }, data });
|
|
88
94
|
{{else if useDrizzle}}
|
|
@@ -103,6 +109,9 @@ export class TodoResolver {
|
|
|
103
109
|
{{#if useTypeorm}}
|
|
104
110
|
const result = await this.db.getRepository(Todo).delete(id);
|
|
105
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;
|
|
106
115
|
{{else if usePrisma}}
|
|
107
116
|
await this.db.prisma.todo.delete({ where: { id } });
|
|
108
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
|
});
|