@nest-arch/tui 0.2.8 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -42
- package/dist/cli.js +1 -1
- package/dist/constants-B5MuV-iH.js +1 -0
- package/dist/index.js +365 -98
- package/dist/templates/addons/husky/pre-commit.hbs +11 -26
- package/dist/templates/base/.env.example.hbs +13 -2
- package/dist/templates/base/.env.hbs +11 -2
- package/dist/templates/base/.gitignore.hbs +2 -1
- package/dist/templates/base/.yarnrc.yml.hbs +0 -5
- package/dist/templates/base/README.md.hbs +49 -5
- package/dist/templates/base/nest-cli.json.hbs +2 -1
- package/dist/templates/base/pnpm-workspace.yaml.hbs +15 -0
- package/dist/templates/base/prisma.config.ts.hbs +32 -6
- package/dist/templates/base/src/app.controller.spec.ts.hbs +3 -11
- package/dist/templates/base/src/app.controller.ts.hbs +2 -2
- package/dist/templates/base/src/app.module.ts.hbs +76 -5
- package/dist/templates/base/src/app.router.ts.hbs +3 -4
- package/dist/templates/base/src/database/adapters/interfaces/db-adapter.interface.ts.hbs +7 -0
- package/dist/templates/base/src/database/adapters/mongo/prisma-mongo.adapter.ts.hbs +36 -4
- package/dist/templates/base/src/database/adapters/mongo/raw-mongo.adapter.ts.hbs +17 -12
- package/dist/templates/base/src/database/adapters/sql/drizzle-sql.adapter.ts.hbs +9 -0
- package/dist/templates/base/src/database/adapters/sql/prisma-sql.adapter.ts.hbs +8 -5
- package/dist/templates/base/src/database/adapters/sql/raw-sql.adapter.ts.hbs +37 -0
- package/dist/templates/base/src/database/adapters/sql/typeorm-sql.adapter.ts.hbs +8 -3
- package/dist/templates/base/src/database/db.module.ts.hbs +55 -42
- package/dist/templates/base/src/database/db.service.ts.hbs +60 -6
- package/dist/templates/base/src/database/entities/app.entity.ts.hbs +25 -0
- package/dist/templates/base/src/database/entities/todo.entity.ts.hbs +12 -7
- package/dist/templates/base/src/database/index.ts.hbs +20 -0
- package/dist/templates/base/src/database/orm/drizzle/schema.ts.hbs +80 -7
- package/dist/templates/base/src/database/orm/typeorm/data-source.ts.hbs +23 -4
- package/dist/templates/base/src/libs/middlewares/auth.trpc.middleware.ts.hbs +47 -0
- package/dist/templates/base/src/libs/middlewares/rate-limit.trpc.middleware.ts.hbs +43 -0
- package/dist/templates/base/src/libs/trpc/error.handler.ts.hbs +1 -1
- package/dist/templates/base/src/libs/trpc/inner.context.ts.hbs +6 -3
- package/dist/templates/base/src/main.ts.hbs +34 -10
- package/dist/templates/base/src/modules/users/entities/user.entity.ts.hbs +22 -0
- package/dist/templates/base/test/app.e2e-spec.ts.hbs +841 -6
- package/dist/templates/base/test/bootstrap.e2e-spec.ts.hbs +84 -0
- package/dist/templates/base/tsconfig.build.json.hbs +2 -0
- package/dist/templates/base/vitest.config.e2e.ts.hbs +4 -3
- package/dist/templates/base/vitest.config.ts.hbs +4 -3
- package/dist/templates/base/yarn.lock.hbs +1 -0
- package/dist/templates/extras/docker/.dockerignore.hbs +8 -1
- package/dist/templates/extras/docker/Dockerfile.hbs +11 -10
- package/dist/templates/extras/health/src/health/health.controller.ts.hbs +54 -0
- package/dist/templates/extras/health/src/health/health.module.ts.hbs +9 -0
- package/dist/templates/extras/swagger/create-docs.ts.hbs +13 -22
- package/dist/templates/feature/graphql/src/graphql/graphql.module.ts.hbs +6 -10
- package/dist/templates/feature/graphql/src/graphql/models/todo.model.ts.hbs +4 -0
- package/dist/templates/feature/graphql/src/graphql/orm/drizzle/drizzle-graphql.module.ts.hbs +6 -4
- package/dist/templates/feature/graphql/src/graphql/resolvers/health.resolver.ts.hbs +14 -0
- package/dist/templates/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +210 -47
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/create-todo.dto.ts.hbs +12 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/dto/update-todo.dto.ts.hbs +12 -0
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.controller.ts.hbs +21 -9
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.module.ts.hbs +1 -3
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.router.ts.hbs +41 -13
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.service.ts.hbs +157 -33
- package/dist/templates/monorepo/apps/api-gateway/package.json.hbs +2 -3
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.spec.ts.hbs +6 -1
- package/dist/templates/monorepo/apps/api-gateway/src/app.controller.ts.hbs +6 -0
- package/dist/templates/monorepo/apps/api-gateway/src/app.module.ts.hbs +32 -1
- package/dist/templates/monorepo/apps/api-gateway/src/app.service.ts.hbs +1 -1
- package/dist/templates/monorepo/apps/api-gateway/src/main.ts.hbs +13 -4
- package/dist/templates/monorepo/apps/api-gateway/test/app.e2e-spec.ts.hbs +45 -1
- package/dist/templates/monorepo/apps/api-gateway/tsconfig.build.json.hbs +2 -1
- package/dist/templates/monorepo/apps/api-gateway/vitest.config.e2e.ts.hbs +3 -2
- package/dist/templates/monorepo/apps/api-gateway/vitest.config.ts.hbs +3 -2
- package/dist/templates/monorepo/feature/graphql/src/graphql/graphql.module.ts.hbs +6 -10
- package/dist/templates/monorepo/feature/graphql/src/graphql/resolvers/health.resolver.ts.hbs +14 -0
- package/dist/templates/monorepo/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +151 -42
- package/dist/templates/monorepo/packages/env/src/api-gateway.ts.hbs +16 -3
- package/dist/templates/monorepo/packages/shared/package.json.hbs +1 -0
- package/dist/templates/monorepo/packages/shared/src/auth.ts.hbs +6 -0
- package/dist/templates/monorepo/root/.gitignore.hbs +1 -0
- package/dist/templates/monorepo/root/pnpm-workspace.yaml.hbs +19 -2
- package/dist/templates/monorepo/root/tsconfig.json.hbs +1 -1
- package/dist/templates/monorepo/root/turbo.json.hbs +2 -0
- package/dist/templates/single-project/architecture/nest-api/.env.hbs +9 -1
- package/dist/templates/single-project/architecture/nest-api/package.json.hbs +1 -2
- package/dist/templates/single-project/architecture/nest-api/src/main.ts.hbs +33 -9
- package/dist/templates/single-project/architecture/nest-gateway/src/main.ts.hbs +3 -3
- package/dist/templates/single-project/architecture/nest-microservice/.env.hbs +18 -0
- package/dist/templates/single-project/architecture/nest-microservice/proto/app.proto.hbs +26 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/app.controller.ts.hbs +23 -4
- package/dist/templates/single-project/architecture/nest-microservice/src/app.service.ts.hbs +6 -2
- package/dist/templates/single-project/architecture/nest-microservice/src/main.ts.hbs +16 -5
- package/dist/templates/single-project/architecture/nest-microservice/test/microservice.e2e-spec.ts.hbs +70 -0
- package/dist/templates/single-project/shared/config/env.ts.hbs +38 -3
- package/package.json +5 -2
- package/dist/constants-Cgtoxhmd.js +0 -1
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { createServer } from "node:net";
|
|
4
|
+
import { spawn, type ChildProcess } from "node:child_process";
|
|
5
|
+
|
|
6
|
+
import { afterEach, expect, it } from "vitest";
|
|
7
|
+
|
|
8
|
+
const startedProcesses: ChildProcess[] = [];
|
|
9
|
+
|
|
10
|
+
async function getFreePort(): Promise<number> {
|
|
11
|
+
const server = createServer();
|
|
12
|
+
server.listen(0, "127.0.0.1");
|
|
13
|
+
await once(server, "listening");
|
|
14
|
+
const address = server.address();
|
|
15
|
+
server.close();
|
|
16
|
+
if (!address || typeof address === "string") {
|
|
17
|
+
throw new Error("Could not allocate a loopback port for the bootstrap test.");
|
|
18
|
+
}
|
|
19
|
+
return address.port;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async function waitForServer(url: string, application: ChildProcess, deadline = Date.now() + 15000): Promise<Response> {
|
|
23
|
+
if (application.exitCode !== null) throw new Error(`Generated application exited during startup with code ${application.exitCode}.`);
|
|
24
|
+
try {
|
|
25
|
+
return await fetch(url, { signal: AbortSignal.timeout(500) });
|
|
26
|
+
} catch (error) {
|
|
27
|
+
if (Date.now() >= deadline) throw new Error("Generated application did not become ready", { cause: error });
|
|
28
|
+
await delay(100);
|
|
29
|
+
return waitForServer(url, application, deadline);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function stopApplication(application: ChildProcess): Promise<void> {
|
|
34
|
+
if (application.exitCode !== null) return;
|
|
35
|
+
const exited = once(application, "exit");
|
|
36
|
+
application.kill();
|
|
37
|
+
const timeout = setTimeout(() => { application.kill("SIGKILL"); }, 5000);
|
|
38
|
+
try { await exited; } finally { clearTimeout(timeout); }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
afterEach(async () => {
|
|
42
|
+
await Promise.all(startedProcesses.splice(0).map(stopApplication));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("boots the compiled application through main.ts", async () => {
|
|
46
|
+
const port = await getFreePort();
|
|
47
|
+
const origin = "https://allowed.example";
|
|
48
|
+
const application = spawn(process.execPath, ["dist/main.js"], {
|
|
49
|
+
env: {
|
|
50
|
+
...process.env,
|
|
51
|
+
CORS_ORIGIN: origin,
|
|
52
|
+
{{#if (and isPassportAuth (not hasDatabase))}}
|
|
53
|
+
OIDC_AUDIENCE: "generated-resource-server",
|
|
54
|
+
OIDC_ISSUER: "https://identity.example.test/",
|
|
55
|
+
OIDC_JWKS_URI: "https://identity.example.test/.well-known/jwks.json",
|
|
56
|
+
{{/if}}
|
|
57
|
+
NODE_ENV: "test",
|
|
58
|
+
PORT: String(port),
|
|
59
|
+
},
|
|
60
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
61
|
+
});
|
|
62
|
+
startedProcesses.push(application);
|
|
63
|
+
let output = "";
|
|
64
|
+
application.stdout?.on("data", (chunk) => { output += chunk.toString(); });
|
|
65
|
+
application.stderr?.on("data", (chunk) => { output += chunk.toString(); });
|
|
66
|
+
|
|
67
|
+
{{#if hasRest}}
|
|
68
|
+
const response = await waitForServer(`http://127.0.0.1:${port}/api`, application).catch((error) => { throw new Error(`${error}\n${output}`); });
|
|
69
|
+
expect(response.status).toBe(200);
|
|
70
|
+
expect(await response.text()).toBe("Hello World!");
|
|
71
|
+
|
|
72
|
+
const corsResponse = await fetch(`http://127.0.0.1:${port}/api`, {
|
|
73
|
+
headers: { Origin: origin },
|
|
74
|
+
});
|
|
75
|
+
expect(corsResponse.headers.get("access-control-allow-origin")).toBe(origin);
|
|
76
|
+
const rootResponse = await fetch(`http://127.0.0.1:${port}/`, { redirect: "manual" });
|
|
77
|
+
expect(rootResponse.status).toBe(404);
|
|
78
|
+
{{else}}
|
|
79
|
+
await waitForServer(`http://127.0.0.1:${port}/graphql?query=%7Bhello%7D`, application).catch((error) => { throw new Error(`${error}\n${output}`); });
|
|
80
|
+
const response = await fetch(`http://127.0.0.1:${port}/graphql`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ query: "{ hello }" }) });
|
|
81
|
+
const body = await response.json();
|
|
82
|
+
expect(body.data.hello).toBe("Hello GraphQL!");
|
|
83
|
+
{{/if}}
|
|
84
|
+
}, 20_000);
|
|
@@ -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: ["**/*.e2e-spec.ts"],
|
|
7
9
|
globals: true,
|
|
8
10
|
root: "./",
|
|
9
|
-
include: ["**/*.e2e-spec.ts"],
|
|
10
11
|
},
|
|
11
12
|
});
|
|
@@ -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.
|
|
@@ -3,20 +3,21 @@ FROM node:22-alpine
|
|
|
3
3
|
WORKDIR /app
|
|
4
4
|
|
|
5
5
|
{{#if (eq packageManager "pnpm")}}
|
|
6
|
-
RUN corepack enable
|
|
7
|
-
COPY package.json pnpm-lock.yaml ./
|
|
8
|
-
RUN pnpm install --frozen-lockfile
|
|
6
|
+
RUN corepack enable
|
|
9
7
|
{{else if (eq packageManager "yarn")}}
|
|
10
|
-
|
|
11
|
-
RUN yarn install --frozen-lockfile
|
|
8
|
+
RUN corepack enable
|
|
12
9
|
{{else}}
|
|
13
|
-
COPY package*.json ./
|
|
14
|
-
RUN npm ci
|
|
15
10
|
{{/if}}
|
|
16
11
|
|
|
17
12
|
COPY . .
|
|
18
|
-
RUN {{packageManager}}
|
|
13
|
+
RUN POSTGRES_URL=postgresql://postgres:postgres@postgres:5432/build_db MYSQL_URL=mysql://root:mysql@mysql:3306/build_db MONGODB_URL=mongodb://mongodb:27017/build_db {{#if (eq auth "passport")}}JWT_ACCESS_SECRET=build-only-access-secret-that-is-long-enough JWT_REFRESH_SECRET=build-only-refresh-secret-that-is-long-enough {{/if}}{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}BETTER_AUTH_SECRET=build-only-better-auth-secret-that-is-long-enough BETTER_AUTH_URL=http://localhost:{{#if (eq httpProvider "fastify")}}3001{{else}}3000{{/if}} {{/if}}{{#if (eq packageManager "pnpm")}}pnpm install --no-lockfile{{else if (eq packageManager "yarn")}}yarn install{{else if (eq packageManager "bun")}}bun install{{else}}npm install{{/if}}
|
|
14
|
+
RUN {{#if (eq packageManager "pnpm")}}pnpm run{{else if (eq packageManager "yarn")}}yarn{{else if (eq packageManager "bun")}}bun run{{else}}npm run{{/if}} build
|
|
19
15
|
|
|
20
|
-
|
|
16
|
+
ENV NODE_ENV=production
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
EXPOSE {{#if (eq httpProvider "fastify")}}3001{{else}}3000{{/if}}
|
|
19
|
+
{{#if (includes microservices "grpc")}}
|
|
20
|
+
EXPOSE 5000
|
|
21
|
+
{{/if}}
|
|
22
|
+
|
|
23
|
+
CMD ["node", "dist/main"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Controller, Get } from "@nestjs/common";
|
|
2
|
+
import { HealthCheck, HealthCheckService } from "@nestjs/terminus";
|
|
3
|
+
{{#if isBetterAuth}}
|
|
4
|
+
import { AllowAnonymous } from "@thallesp/nestjs-better-auth";
|
|
5
|
+
{{/if}}
|
|
6
|
+
{{#if hasDatabase}}
|
|
7
|
+
import { DbService } from "../database/db.service.js";
|
|
8
|
+
{{#if useDrizzle}}
|
|
9
|
+
import { sql } from "drizzle-orm";
|
|
10
|
+
{{/if}}
|
|
11
|
+
{{/if}}
|
|
12
|
+
|
|
13
|
+
{{#if isBetterAuth}}
|
|
14
|
+
@AllowAnonymous()
|
|
15
|
+
{{/if}}
|
|
16
|
+
@Controller("health")
|
|
17
|
+
export class HealthController {
|
|
18
|
+
constructor(
|
|
19
|
+
private readonly health: HealthCheckService{{#if hasDatabase}},
|
|
20
|
+
private readonly db: DbService{{/if}}
|
|
21
|
+
) {}
|
|
22
|
+
|
|
23
|
+
@Get()
|
|
24
|
+
@HealthCheck()
|
|
25
|
+
check() {
|
|
26
|
+
return this.health.check([
|
|
27
|
+
() => ({ app: { status: "up" } }),
|
|
28
|
+
{{#if hasDatabase}}
|
|
29
|
+
async () => {
|
|
30
|
+
try {
|
|
31
|
+
{{#if (or usePrisma isPrisma8)}}
|
|
32
|
+
await this.db.prisma.$queryRaw`SELECT 1`;
|
|
33
|
+
{{else if useDrizzle}}
|
|
34
|
+
{{#if hasSqlite}}
|
|
35
|
+
await this.db.drizzle.get(sql`SELECT 1`);
|
|
36
|
+
{{else}}
|
|
37
|
+
await this.db.drizzle.execute(sql`SELECT 1`);
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{else if useTypeorm}}
|
|
40
|
+
await this.db.typeorm.query("SELECT 1");
|
|
41
|
+
{{else if hasMongodb}}
|
|
42
|
+
await this.db.raw.mongo.command({ ping: 1 });
|
|
43
|
+
{{else}}
|
|
44
|
+
await this.db.raw.sql.query("SELECT 1");
|
|
45
|
+
{{/if}}
|
|
46
|
+
return { db: { status: "up" } };
|
|
47
|
+
} catch {
|
|
48
|
+
return { db: { status: "down" } };
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
{{/if}}
|
|
52
|
+
]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Module } from "@nestjs/common";
|
|
2
|
+
import { TerminusModule } from "@nestjs/terminus";
|
|
3
|
+
import { HealthController } from "./health.controller.js";
|
|
4
|
+
|
|
5
|
+
@Module({
|
|
6
|
+
controllers: [HealthController],
|
|
7
|
+
imports: [TerminusModule],
|
|
8
|
+
})
|
|
9
|
+
export class HealthModule {}
|
|
@@ -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";
|
|
@@ -23,6 +19,7 @@ interface DocsIntegrations {
|
|
|
23
19
|
zod?: {
|
|
24
20
|
withFastify?: boolean;
|
|
25
21
|
};
|
|
22
|
+
bearerAuth?: boolean;
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
export interface CreateDocsOptions {
|
|
@@ -80,7 +77,8 @@ async function applyZodCleanup(
|
|
|
80
77
|
options?: NonNullable<DocsIntegrations["zod"]>
|
|
81
78
|
) {
|
|
82
79
|
try {
|
|
83
|
-
const
|
|
80
|
+
const packageName = "nestjs-zod";
|
|
81
|
+
const { cleanupOpenApiDoc } = await import(packageName);
|
|
84
82
|
if (typeof cleanupOpenApiDoc !== "function") {
|
|
85
83
|
return baseSpec;
|
|
86
84
|
}
|
|
@@ -143,7 +141,8 @@ async function applyTrpcSpec(options?: NonNullable<DocsIntegrations["trpc"]>) {
|
|
|
143
141
|
}
|
|
144
142
|
|
|
145
143
|
try {
|
|
146
|
-
const
|
|
144
|
+
const packageName = "@trpc/openapi";
|
|
145
|
+
const { generateOpenAPIDocument } = await import(packageName);
|
|
147
146
|
|
|
148
147
|
if (typeof generateOpenAPIDocument !== "function") {
|
|
149
148
|
return null;
|
|
@@ -174,28 +173,20 @@ async function applyTrpcSpec(options?: NonNullable<DocsIntegrations["trpc"]>) {
|
|
|
174
173
|
}
|
|
175
174
|
}
|
|
176
175
|
|
|
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
176
|
export async function createDocs(
|
|
191
177
|
app: INestApplication,
|
|
192
178
|
options: CreateDocsOptions = {}
|
|
193
179
|
): Promise<OpenAPIObject> {
|
|
194
|
-
const
|
|
180
|
+
const builder = new DocumentBuilder()
|
|
195
181
|
.setTitle(options.title ?? "NestJS API")
|
|
196
182
|
.setDescription(options.description ?? "Generated with Nest Arch")
|
|
197
|
-
.setVersion(options.version ?? "1.0.0")
|
|
198
|
-
|
|
183
|
+
.setVersion(options.version ?? "1.0.0");
|
|
184
|
+
|
|
185
|
+
if (options.integrations?.bearerAuth === true) {
|
|
186
|
+
builder.addBearerAuth();
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
const config = builder.build();
|
|
199
190
|
|
|
200
191
|
let baseSpec = SwaggerModule.createDocument(app, config) as OpenAPIObject;
|
|
201
192
|
baseSpec = await applyZodCleanup(baseSpec, options.integrations?.zod);
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { Module } from "@nestjs/common";
|
|
2
2
|
import { GraphQLModule } from "@nestjs/graphql";
|
|
3
3
|
import { ApolloDriver, ApolloDriverConfig } from "@nestjs/apollo";
|
|
4
|
-
import {
|
|
4
|
+
import type { IncomingMessage } from "node:http";
|
|
5
|
+
import path from "node:path";
|
|
5
6
|
import { env } from "../config/env.js";
|
|
6
|
-
{
|
|
7
|
-
// WARNING: If you use @as-integrations/fastify with multiple GraphQL endpoints
|
|
8
|
-
// in a single application, make sure to enable the disableHealthCheck setting
|
|
9
|
-
// in the GraphQLModule configuration below.
|
|
10
|
-
{{/if}}
|
|
7
|
+
import { HealthResolver } from "./resolvers/health.resolver.js";
|
|
11
8
|
{{#if hasTodoExample}}
|
|
12
9
|
import { TodoResolver } from "./resolvers/todo.resolver.js";
|
|
13
10
|
{{/if}}
|
|
@@ -16,15 +13,14 @@ import { TodoResolver } from "./resolvers/todo.resolver.js";
|
|
|
16
13
|
imports: [
|
|
17
14
|
GraphQLModule.forRoot<ApolloDriverConfig>({
|
|
18
15
|
driver: ApolloDriver,
|
|
19
|
-
autoSchemaFile: join(process.cwd(), "src/schema.gql"),
|
|
16
|
+
autoSchemaFile: path.join(process.cwd(), "src/schema.gql"),
|
|
20
17
|
graphiql: env.GRAPHQL_PLAYGROUND,
|
|
18
|
+
context: ({ req, res }: { req: IncomingMessage; res: unknown }) => ({ req, res }),
|
|
21
19
|
sortSchema: true,
|
|
22
|
-
{{#if (eq httpProvider "fastify")}}
|
|
23
|
-
disableHealthCheck: true,
|
|
24
|
-
{{/if}}
|
|
25
20
|
}),
|
|
26
21
|
],
|
|
27
22
|
providers: [
|
|
23
|
+
HealthResolver,
|
|
28
24
|
{{#if hasTodoExample}}
|
|
29
25
|
TodoResolver,
|
|
30
26
|
{{/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";
|
|
@@ -15,21 +16,22 @@ import mysql from "mysql2";
|
|
|
15
16
|
import { drizzle } from "drizzle-orm/better-sqlite3";
|
|
16
17
|
import Database from "better-sqlite3";
|
|
17
18
|
{{/if}}
|
|
18
|
-
import * as dbSchema from "
|
|
19
|
+
import * as dbSchema from "../../../database/orm/drizzle/schema.js";
|
|
19
20
|
{{/if}}
|
|
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), { mode: "default", 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
|
|
|
34
|
+
|
|
33
35
|
@Module({
|
|
34
36
|
providers: [
|
|
35
37
|
{
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Query, Resolver } from "@nestjs/graphql";
|
|
2
|
+
{{#if isBetterAuth}}
|
|
3
|
+
import { AllowAnonymous } from "@thallesp/nestjs-better-auth";
|
|
4
|
+
{{/if}}
|
|
5
|
+
{{#if isBetterAuth}}
|
|
6
|
+
@AllowAnonymous()
|
|
7
|
+
{{/if}}
|
|
8
|
+
@Resolver()
|
|
9
|
+
export class HealthResolver {
|
|
10
|
+
@Query(() => String)
|
|
11
|
+
hello(): string {
|
|
12
|
+
return "Hello GraphQL!";
|
|
13
|
+
}
|
|
14
|
+
}
|