@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,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,18 +1,7 @@
|
|
|
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
|
-
{
|
|
8
|
-
import {
|
|
9
|
-
DocumentBuilder,
|
|
10
|
-
SwaggerModule,
|
|
11
|
-
type OpenAPIObject,
|
|
12
|
-
} from "@nestjs/swagger";
|
|
13
|
-
{{else}}
|
|
3
|
+
import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger";
|
|
14
4
|
import type { OpenAPIObject } from "@nestjs/swagger";
|
|
15
|
-
{{/if}}
|
|
16
5
|
|
|
17
6
|
interface DocsIntegrations {
|
|
18
7
|
betterAuth?: {
|
|
@@ -40,65 +29,16 @@ export interface CreateDocsOptions {
|
|
|
40
29
|
integrations?: DocsIntegrations;
|
|
41
30
|
}
|
|
42
31
|
|
|
43
|
-
function rewriteRefs(value: unknown): unknown {
|
|
44
|
-
if (Array.isArray(value)) {
|
|
45
|
-
return value.map((item) => rewriteRefs(item));
|
|
46
|
-
}
|
|
47
|
-
if (!value || typeof value !== "object") {
|
|
48
|
-
return value;
|
|
49
|
-
}
|
|
50
|
-
const obj = value as Record<string, unknown>;
|
|
51
|
-
if (typeof obj.$ref === "string") {
|
|
52
|
-
const rest = rewriteRefs(
|
|
53
|
-
Object.fromEntries(Object.entries(obj).filter(([k]) => k !== "$ref"))
|
|
54
|
-
) as Record<string, unknown>;
|
|
55
|
-
return {
|
|
56
|
-
...rest,
|
|
57
|
-
$ref: (obj.$ref as string)
|
|
58
|
-
.replace("#/$defs/", "#/components/schemas/")
|
|
59
|
-
.replace("#/definitions/", "#/components/schemas/"),
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
return Object.fromEntries(
|
|
63
|
-
Object.entries(obj).map(([k, v]) => [k, rewriteRefs(v)])
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
function normalizeSchema(
|
|
68
|
-
schema: unknown,
|
|
69
|
-
components: Record<string, unknown> = {}
|
|
70
|
-
): ReturnType<StandardSchemaConverter> {
|
|
71
|
-
const raw = (
|
|
72
|
-
typeof schema === "object" && schema !== null ? schema : {}
|
|
73
|
-
) as Record<string, unknown>;
|
|
74
|
-
const normalizedComponents = Object.fromEntries(
|
|
75
|
-
Object.entries(raw.$defs ?? {}).map(([name, def]) => [
|
|
76
|
-
name,
|
|
77
|
-
rewriteRefs(def),
|
|
78
|
-
])
|
|
79
|
-
);
|
|
80
|
-
const filtered: Record<string, unknown> = {};
|
|
81
|
-
for (const key of Object.keys(raw)) {
|
|
82
|
-
if (key !== "$defs" && key !== "definitions" && key !== "$schema") {
|
|
83
|
-
filtered[key] = raw[key];
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
return {
|
|
87
|
-
components: {
|
|
88
|
-
...components,
|
|
89
|
-
...normalizedComponents,
|
|
90
|
-
},
|
|
91
|
-
schema: rewriteRefs(filtered),
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
32
|
function addPrefixToPaths(paths: Record<string, unknown>, prefix: string) {
|
|
96
33
|
return Object.fromEntries(
|
|
97
34
|
Object.entries(paths).map(([path, value]) => [`${prefix}${path}`, value])
|
|
98
35
|
);
|
|
99
36
|
}
|
|
100
37
|
|
|
101
|
-
function mergeOpenApiSpecs(
|
|
38
|
+
function mergeOpenApiSpecs(
|
|
39
|
+
baseSpec: OpenAPIObject,
|
|
40
|
+
...extraSpecs: OpenAPIObject[]
|
|
41
|
+
) {
|
|
102
42
|
const specs = [baseSpec, ...extraSpecs];
|
|
103
43
|
|
|
104
44
|
return {
|
|
@@ -131,6 +71,29 @@ function mergeOpenApiSpecs(baseSpec: OpenAPIObject, ...extraSpecs: OpenAPIObject
|
|
|
131
71
|
} as OpenAPIObject;
|
|
132
72
|
}
|
|
133
73
|
|
|
74
|
+
async function applyZodCleanup(
|
|
75
|
+
baseSpec: OpenAPIObject,
|
|
76
|
+
options?: NonNullable<DocsIntegrations["zod"]>
|
|
77
|
+
) {
|
|
78
|
+
try {
|
|
79
|
+
const packageName = "nestjs-zod";
|
|
80
|
+
const { cleanupOpenApiDoc } = await import(packageName);
|
|
81
|
+
if (typeof cleanupOpenApiDoc !== "function") {
|
|
82
|
+
return baseSpec;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (options?.withFastify === true) {
|
|
86
|
+
return cleanupOpenApiDoc(baseSpec, {
|
|
87
|
+
withFastify: true,
|
|
88
|
+
}) as OpenAPIObject;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return cleanupOpenApiDoc(baseSpec) as OpenAPIObject;
|
|
92
|
+
} catch {
|
|
93
|
+
return baseSpec;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
134
97
|
async function applyBetterAuthSpec(
|
|
135
98
|
options?: NonNullable<DocsIntegrations["betterAuth"]>
|
|
136
99
|
) {
|
|
@@ -145,7 +108,9 @@ async function applyBetterAuthSpec(
|
|
|
145
108
|
generateOpenAPISchema?: () => OpenAPIObject | Promise<OpenAPIObject>;
|
|
146
109
|
};
|
|
147
110
|
|
|
148
|
-
const schemaGenerator =
|
|
111
|
+
const schemaGenerator =
|
|
112
|
+
authInstance.api?.generateOpenAPISchema ??
|
|
113
|
+
authInstance.generateOpenAPISchema;
|
|
149
114
|
|
|
150
115
|
if (typeof schemaGenerator !== "function") {
|
|
151
116
|
return null;
|
|
@@ -169,29 +134,27 @@ async function applyBetterAuthSpec(
|
|
|
169
134
|
}
|
|
170
135
|
}
|
|
171
136
|
|
|
172
|
-
async function applyTrpcSpec(
|
|
173
|
-
options?: NonNullable<DocsIntegrations["trpc"]>
|
|
174
|
-
) {
|
|
137
|
+
async function applyTrpcSpec(options?: NonNullable<DocsIntegrations["trpc"]>) {
|
|
175
138
|
if (!options?.routerFilePath) {
|
|
176
139
|
return null;
|
|
177
140
|
}
|
|
178
141
|
|
|
179
142
|
try {
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
const generateOpenAPIDocument = mod.generateOpenAPIDocument as
|
|
183
|
-
| ((opts: unknown, config: unknown) => unknown)
|
|
184
|
-
| undefined;
|
|
143
|
+
const packageName = "@trpc/openapi";
|
|
144
|
+
const { generateOpenAPIDocument } = await import(packageName);
|
|
185
145
|
|
|
186
146
|
if (typeof generateOpenAPIDocument !== "function") {
|
|
187
147
|
return null;
|
|
188
148
|
}
|
|
189
149
|
|
|
190
|
-
const generatedDocument = await generateOpenAPIDocument(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
150
|
+
const generatedDocument = await generateOpenAPIDocument(
|
|
151
|
+
options.routerFilePath,
|
|
152
|
+
{
|
|
153
|
+
exportName: options.exportName ?? "AppRouter",
|
|
154
|
+
title: options.title ?? "tRPC API",
|
|
155
|
+
version: options.version ?? "1.0.0",
|
|
156
|
+
}
|
|
157
|
+
);
|
|
195
158
|
|
|
196
159
|
const trpcSpec = generatedDocument as OpenAPIObject;
|
|
197
160
|
const prefix = options.pathPrefix ?? "/trpc";
|
|
@@ -208,53 +171,19 @@ async function applyTrpcSpec(
|
|
|
208
171
|
return null;
|
|
209
172
|
}
|
|
210
173
|
}
|
|
211
|
-
function createEmptyBaseSpec(options: CreateDocsOptions): OpenAPIObject {
|
|
212
|
-
return {
|
|
213
|
-
info: {
|
|
214
|
-
title: options.title ?? "NestJS API",
|
|
215
|
-
description: options.description ?? "Generated with Nest Arch",
|
|
216
|
-
version: options.version ?? "1.0.0",
|
|
217
|
-
},
|
|
218
|
-
openapi: "3.1.0",
|
|
219
|
-
paths: {},
|
|
220
|
-
tags: [],
|
|
221
|
-
} as OpenAPIObject;
|
|
222
|
-
}
|
|
223
174
|
|
|
224
175
|
export async function createDocs(
|
|
225
176
|
app: INestApplication,
|
|
226
177
|
options: CreateDocsOptions = {}
|
|
227
178
|
): Promise<OpenAPIObject> {
|
|
228
|
-
{{#if (or hasRest hasAuth)}}
|
|
229
179
|
const config = new DocumentBuilder()
|
|
230
180
|
.setTitle(options.title ?? "NestJS API")
|
|
231
181
|
.setDescription(options.description ?? "Generated with Nest Arch")
|
|
232
182
|
.setVersion(options.version ?? "1.0.0")
|
|
233
183
|
.build();
|
|
234
184
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
{ schemaType }
|
|
238
|
-
) => {
|
|
239
|
-
const standard = (schema as Record<string, unknown> | undefined)?.[
|
|
240
|
-
"~standard"
|
|
241
|
-
] as Record<string, unknown> | undefined;
|
|
242
|
-
const convert = standard?.jsonSchema?.[schemaType] as
|
|
243
|
-
| ((opts: { target: string }) => unknown)
|
|
244
|
-
| undefined;
|
|
245
|
-
if (!convert) {
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const converted = convert({ target: "openapi-3.0" });
|
|
249
|
-
if (!converted || typeof converted !== "object") {
|
|
250
|
-
return;
|
|
251
|
-
}
|
|
252
|
-
return normalizeSchema(converted);
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
let baseSpec = SwaggerModule.createDocument(app, config, {
|
|
256
|
-
standardSchemaConverter,
|
|
257
|
-
}) as OpenAPIObject;
|
|
185
|
+
let baseSpec = SwaggerModule.createDocument(app, config) as OpenAPIObject;
|
|
186
|
+
baseSpec = await applyZodCleanup(baseSpec, options.integrations?.zod);
|
|
258
187
|
|
|
259
188
|
if (!baseSpec.paths || Object.keys(baseSpec.paths).length === 0) {
|
|
260
189
|
baseSpec = {
|
|
@@ -268,13 +197,12 @@ export async function createDocs(
|
|
|
268
197
|
tags: [],
|
|
269
198
|
} as OpenAPIObject;
|
|
270
199
|
}
|
|
271
|
-
{{else}}
|
|
272
|
-
const baseSpec = createEmptyBaseSpec(options);
|
|
273
|
-
{{/if}}
|
|
274
200
|
|
|
275
201
|
const additionalSpecs: OpenAPIObject[] = [];
|
|
276
202
|
|
|
277
|
-
const betterAuthSpec = await applyBetterAuthSpec(
|
|
203
|
+
const betterAuthSpec = await applyBetterAuthSpec(
|
|
204
|
+
options.integrations?.betterAuth
|
|
205
|
+
);
|
|
278
206
|
if (betterAuthSpec) {
|
|
279
207
|
additionalSpecs.push(betterAuthSpec);
|
|
280
208
|
}
|
|
@@ -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,28 +1,70 @@
|
|
|
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}}
|
|
4
44
|
import { Args, Mutation, Query, Resolver } from "@nestjs/graphql";
|
|
5
|
-
|
|
6
|
-
import {
|
|
45
|
+
{{#if (and hasAuth hasDatabase)}}
|
|
46
|
+
import { UserEntity } from "../../auth/decorators/index.js";
|
|
47
|
+
import { GqlAuthGuard } from "../../auth/guards/gql-auth.guard.js";
|
|
48
|
+
{{/if}}
|
|
7
49
|
{{#if isMonorepo}}
|
|
8
50
|
import { DbService } from "@repo/db";
|
|
9
51
|
{{else}}
|
|
10
|
-
import { DbService } from "
|
|
52
|
+
import { DbService } from "../../database/db.service.js";
|
|
11
53
|
{{/if}}
|
|
54
|
+
import { CreateTodoInput } from "../dto/create-todo.input.js";
|
|
55
|
+
import { UpdateTodoInput } from "../dto/update-todo.input.js";
|
|
12
56
|
{{#if useTypeorm}}
|
|
13
57
|
import { GraphRelationBuilder } from "typeorm-relations-graphql";
|
|
14
58
|
import { GraphQLResolveInfo } from "graphql";
|
|
15
59
|
{{/if}}
|
|
16
60
|
{{#if useDrizzle}}
|
|
17
|
-
import * as schema from "
|
|
61
|
+
import * as schema from "../../database/orm/drizzle/schema.js";
|
|
18
62
|
{{/if}}
|
|
19
63
|
{{#if (and hasAuth hasDatabase)}}
|
|
20
64
|
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
65
|
{{/if}}
|
|
24
66
|
|
|
25
|
-
@Resolver(
|
|
67
|
+
@Resolver(() => Todo)
|
|
26
68
|
export class TodoResolver {
|
|
27
69
|
constructor(private readonly db: DbService) {}
|
|
28
70
|
|
|
@@ -32,11 +74,13 @@ export class TodoResolver {
|
|
|
32
74
|
}{{#if hasDatabase}}
|
|
33
75
|
|
|
34
76
|
@Query(() => [Todo])
|
|
35
|
-
todos({{#if useTypeorm}}info: GraphQLResolveInfo{{/if}})
|
|
77
|
+
todos({{#if useTypeorm}}info: GraphQLResolveInfo{{/if}}) {
|
|
36
78
|
{{#if useTypeorm}}
|
|
37
79
|
const builder = new GraphRelationBuilder(this.db.getDataSource());
|
|
38
80
|
const relations = builder.buildForQuery(Todo, info, "todos");
|
|
39
81
|
return this.db.getRepository(Todo).find({ relations });
|
|
82
|
+
{{else if isPrisma8}}
|
|
83
|
+
return ((this.db.prisma.orm.public as any).Todo).all();
|
|
40
84
|
{{else if usePrisma}}
|
|
41
85
|
return this.db.prisma.todo.findMany();
|
|
42
86
|
{{else if useDrizzle}}
|
|
@@ -46,14 +90,12 @@ export class TodoResolver {
|
|
|
46
90
|
{{/if}}
|
|
47
91
|
}
|
|
48
92
|
|
|
49
|
-
@Mutation(() => Todo)
|
|
50
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
51
93
|
@UseGuards(GqlAuthGuard)
|
|
52
|
-
|
|
94
|
+
@Mutation(() => Todo)
|
|
53
95
|
createTodo(
|
|
54
|
-
@
|
|
55
|
-
@
|
|
56
|
-
)
|
|
96
|
+
@UserEntity() user: { id: string },
|
|
97
|
+
@Args("input") input: CreateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
98
|
+
) {
|
|
57
99
|
{{#if useTypeorm}}
|
|
58
100
|
const entity = this.db.getRepository(Todo).create(input);
|
|
59
101
|
const saved = await this.db.getRepository(Todo).save(entity);
|
|
@@ -63,9 +105,11 @@ 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
|
-
data: { ...input
|
|
112
|
+
data: { ...input, authorId: user.id },
|
|
69
113
|
});
|
|
70
114
|
{{else if useDrizzle}}
|
|
71
115
|
const [todo] = await this.db.insert(schema.todos).values(input).returning();
|
|
@@ -75,13 +119,9 @@ export class TodoResolver {
|
|
|
75
119
|
{{/if}}
|
|
76
120
|
}
|
|
77
121
|
|
|
78
|
-
@Mutation(() => Todo)
|
|
79
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
80
122
|
@UseGuards(GqlAuthGuard)
|
|
81
|
-
|
|
82
|
-
updateTodo(
|
|
83
|
-
@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}
|
|
84
|
-
): Promise<Todo> {
|
|
123
|
+
@Mutation(() => Todo)
|
|
124
|
+
updateTodo(@Args("input") input: UpdateTodoInput{{#if useTypeorm}}, info: GraphQLResolveInfo{{/if}}) {
|
|
85
125
|
const { id, ...data } = input;
|
|
86
126
|
{{#if useTypeorm}}
|
|
87
127
|
await this.db.getRepository(Todo).update(id, data);
|
|
@@ -91,6 +131,8 @@ export class TodoResolver {
|
|
|
91
131
|
where: { id },
|
|
92
132
|
relations,
|
|
93
133
|
});
|
|
134
|
+
{{else if isPrisma8}}
|
|
135
|
+
return ((this.db.prisma.orm.public as any).Todo).where({ id }).update(data);
|
|
94
136
|
{{else if usePrisma}}
|
|
95
137
|
return this.db.prisma.todo.update({ where: { id }, data });
|
|
96
138
|
{{else if useDrizzle}}
|
|
@@ -105,14 +147,15 @@ export class TodoResolver {
|
|
|
105
147
|
{{/if}}
|
|
106
148
|
}
|
|
107
149
|
|
|
108
|
-
@Mutation(() => Boolean)
|
|
109
|
-
{{#if (and hasAuth hasDatabase)}}
|
|
110
150
|
@UseGuards(GqlAuthGuard)
|
|
111
|
-
|
|
151
|
+
@Mutation(() => Boolean)
|
|
112
152
|
async deleteTodo(@Args("id") id: string): Promise<boolean> {
|
|
113
153
|
{{#if useTypeorm}}
|
|
114
154
|
const result = await this.db.getRepository(Todo).delete(id);
|
|
115
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;
|
|
116
159
|
{{else if usePrisma}}
|
|
117
160
|
await this.db.prisma.todo.delete({ where: { id } });
|
|
118
161
|
return true;
|
|
@@ -124,3 +167,5 @@ export class TodoResolver {
|
|
|
124
167
|
{{/if}}
|
|
125
168
|
}{{/if}}
|
|
126
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 {}
|