@nest-arch/tui 0.4.6 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/cli.js +2 -1
- package/dist/constants-CUTbfu9C.js +1 -0
- package/dist/index.js +6 -405
- package/dist/nonInteractive-C1KZ0b_6.js +5 -0
- package/dist/nonInteractiveOptions-CIaoLAWg.js +24 -0
- package/dist/projectGeneratorService-CeWJK-HA.js +420 -0
- package/dist/projectName-CcE90t2V.js +1 -0
- package/dist/templates/addons/husky/pre-commit.hbs +1 -1
- package/dist/templates/base/.env.example.hbs +30 -2
- package/dist/templates/base/.env.hbs +7 -2
- package/dist/templates/base/README.md.hbs +11 -2
- package/dist/templates/base/pnpm-workspace.yaml.hbs +9 -4
- package/dist/templates/base/prisma.config.ts.hbs +6 -1
- package/dist/templates/base/src/app.controller.spec.ts.hbs +6 -0
- package/dist/templates/base/src/app.module.ts.hbs +6 -23
- package/dist/templates/base/src/database/adapters/interfaces/db-adapter.interface.ts.hbs +5 -5
- package/dist/templates/base/src/database/adapters/mongo/raw-mongo.adapter.ts.hbs +6 -4
- package/dist/templates/base/src/database/adapters/mongo/typeorm-mongo.adapter.ts.hbs +27 -0
- package/dist/templates/base/src/database/db.module.ts.hbs +33 -13
- package/dist/templates/base/src/database/db.service.ts.hbs +12 -4
- package/dist/templates/base/src/database/entities/todo.entity.ts.hbs +17 -5
- package/dist/templates/base/src/database/index.ts.hbs +2 -0
- package/dist/templates/base/src/database/orm/drizzle/schema.ts.hbs +80 -20
- package/dist/templates/base/src/database/orm/typeorm/data-source.ts.hbs +34 -12
- package/dist/templates/base/src/libs/middlewares/graphql-throttler.guard.ts.hbs +22 -0
- package/dist/templates/base/src/libs/middlewares/rate-limit.trpc.middleware.ts.hbs +2 -1
- package/dist/templates/base/src/libs/trpc/inner.context.ts.hbs +2 -2
- package/dist/templates/base/src/main.ts.hbs +2 -2
- package/dist/templates/base/test/app.e2e-spec.ts.hbs +378 -202
- package/dist/templates/extras/docker/Dockerfile.hbs +9 -2
- package/dist/templates/extras/health/src/health/health.controller.ts.hbs +12 -1
- package/dist/templates/extras/swagger/create-docs.ts.hbs +6 -1
- package/dist/templates/feature/graphql/src/graphql/models/todo.model.ts.hbs +1 -1
- package/dist/templates/feature/graphql/src/graphql/resolvers/todo.resolver.ts.hbs +1 -1
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.controller.ts.hbs +80 -7
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.router.ts.hbs +4 -4
- package/dist/templates/feature/rest/todo-example/src/api/todo/todo.service.ts.hbs +314 -34
- package/dist/templates/monorepo/apps/api-gateway/src/main.ts.hbs +2 -2
- package/dist/templates/monorepo/root/README.md.hbs +8 -13
- package/dist/templates/single-project/architecture/nest-api/.env.hbs +6 -2
- package/dist/templates/single-project/architecture/nest-api/pnpm-workspace.yaml.hbs +6 -0
- package/dist/templates/single-project/architecture/nest-api/src/main.ts.hbs +2 -2
- package/dist/templates/single-project/architecture/nest-gateway/src/main.ts.hbs +2 -2
- package/dist/templates/single-project/architecture/nest-microservice/.env.hbs +30 -1
- 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 +26 -2
- package/dist/templates/single-project/architecture/nest-microservice/src/app.module.ts.hbs +61 -1
- package/dist/templates/single-project/architecture/nest-microservice/src/app.service.ts.hbs +16 -4
- package/dist/templates/single-project/architecture/nest-microservice/src/http-throttler.guard.ts.hbs +13 -0
- package/dist/templates/single-project/architecture/nest-microservice/src/main.ts.hbs +26 -7
- package/dist/templates/single-project/architecture/nest-microservice/test/microservice.e2e-spec.ts.hbs +7 -87
- package/dist/templates/single-project/shared/config/env.ts.hbs +14 -14
- package/package.json +6 -5
- package/dist/constants-DVhgS48N.js +0 -1
|
@@ -1,22 +1,51 @@
|
|
|
1
1
|
PORT=3000
|
|
2
|
+
NODE_ENV=development
|
|
3
|
+
TRUSTED_PROXY_IPS={{#each trustedProxyIps}}{{#unless @first}},{{/unless}}{{this}}{{/each}}
|
|
2
4
|
MICROSERVICE_PORT=3001
|
|
3
|
-
CORS_ORIGIN=http://localhost:
|
|
5
|
+
CORS_ORIGIN=http://localhost:3000
|
|
6
|
+
{{#if hasPostgres}}
|
|
7
|
+
POSTGRES_URL=postgresql://postgres:postgres@localhost:5432/{{projectNameKebab}}_db?schema=public
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if hasMysql}}
|
|
10
|
+
MYSQL_URL=mysql://root:mysql@localhost:3306/{{projectNameKebab}}_db
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if hasSqlite}}
|
|
13
|
+
SQLITE_PATH=./src/database/dev.db
|
|
14
|
+
{{/if}}
|
|
15
|
+
{{#if hasSqlserver}}
|
|
16
|
+
SQLSERVER_HOST=localhost
|
|
17
|
+
SQLSERVER_PORT=1433
|
|
18
|
+
SQLSERVER_DATABASE={{projectNameKebab}}_db
|
|
19
|
+
SQLSERVER_USER=sa
|
|
20
|
+
SQLSERVER_PASSWORD=DevOnly_Strong_Password_2026!X9
|
|
21
|
+
SQLSERVER_ENCRYPT=true
|
|
22
|
+
SQLSERVER_TRUST_SERVER_CERTIFICATE=true
|
|
23
|
+
{{/if}}
|
|
24
|
+
{{#if hasMongodb}}
|
|
25
|
+
MONGODB_URL=mongodb://localhost:27017/{{projectNameKebab}}_db
|
|
26
|
+
{{/if}}
|
|
4
27
|
{{#if (includes microservices "redis")}}
|
|
28
|
+
REDIS_PORT=6379
|
|
5
29
|
REDIS_URL=redis://127.0.0.1:6379
|
|
6
30
|
{{/if}}
|
|
7
31
|
{{#if (includes microservices "mqtt")}}
|
|
32
|
+
MQTT_PORT=1883
|
|
8
33
|
MQTT_URL=mqtt://127.0.0.1:1883
|
|
9
34
|
{{/if}}
|
|
10
35
|
{{#if (includes microservices "nats")}}
|
|
36
|
+
NATS_PORT=4222
|
|
11
37
|
NATS_URL=nats://127.0.0.1:4222
|
|
12
38
|
{{/if}}
|
|
13
39
|
{{#if (includes microservices "rabbitmq")}}
|
|
40
|
+
RABBITMQ_PORT=5672
|
|
14
41
|
RABBITMQ_URL=amqp://127.0.0.1:5672
|
|
15
42
|
{{/if}}
|
|
16
43
|
{{#if (includes microservices "kafka")}}
|
|
44
|
+
KAFKA_PORT=9092
|
|
17
45
|
KAFKA_BROKER=127.0.0.1:9092
|
|
18
46
|
{{/if}}
|
|
19
47
|
{{#if (includes microservices "grpc")}}
|
|
48
|
+
GRPC_PORT=5000
|
|
20
49
|
GRPC_URL=0.0.0.0:5000
|
|
21
50
|
{{/if}}
|
|
22
51
|
{{#if hasGraphql}}
|
|
@@ -5,9 +5,22 @@ package app;
|
|
|
5
5
|
service AppService {
|
|
6
6
|
rpc Ping (PingRequest) returns (PingResponse);
|
|
7
7
|
rpc Log (LogRequest) returns (LogResponse);
|
|
8
|
+
{{#if (and hasDatabase hasTodoExample)}}
|
|
9
|
+
rpc CreateTodo (CreateTodoRequest) returns (StorageResponse);
|
|
10
|
+
rpc ListTodos (PingRequest) returns (StorageResponse);
|
|
11
|
+
{{/if}}
|
|
8
12
|
}
|
|
9
13
|
|
|
10
14
|
message PingRequest {}
|
|
15
|
+
{{#if (and hasDatabase hasTodoExample)}}
|
|
16
|
+
message CreateTodoRequest {
|
|
17
|
+
string title = 1;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
message StorageResponse {
|
|
21
|
+
string json = 1;
|
|
22
|
+
}
|
|
23
|
+
{{/if}}
|
|
11
24
|
|
|
12
25
|
message PingResponse {
|
|
13
26
|
string message = 1;
|
package/dist/templates/single-project/architecture/nest-microservice/src/app.controller.ts.hbs
CHANGED
|
@@ -9,11 +9,11 @@ import { EventPattern, MessagePattern } from "@nestjs/microservices";
|
|
|
9
9
|
import { AppService } from "./app.service.js";
|
|
10
10
|
|
|
11
11
|
{{#unless (includes microservices "grpc")}}
|
|
12
|
-
|
|
12
|
+
interface AuditEvent {
|
|
13
13
|
id: string;
|
|
14
14
|
payload: Record<string, unknown>;
|
|
15
15
|
source: string;
|
|
16
|
-
}
|
|
16
|
+
}
|
|
17
17
|
|
|
18
18
|
const isAuditEvent = (value: unknown): value is AuditEvent => {
|
|
19
19
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
@@ -40,6 +40,30 @@ export class AppController {
|
|
|
40
40
|
|
|
41
41
|
constructor(private readonly appService: AppService) {}
|
|
42
42
|
|
|
43
|
+
{{#if (and hasDatabase hasTodoExample)}}
|
|
44
|
+
{{#if (includes microservices "grpc")}}
|
|
45
|
+
@GrpcMethod("AppService", "CreateTodo")
|
|
46
|
+
async createTodo(data: { title: string }): Promise<{ json: string }> {
|
|
47
|
+
return { json: JSON.stringify(await this.appService.createTodo(data)) };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@GrpcMethod("AppService", "ListTodos")
|
|
51
|
+
async listTodos(): Promise<{ json: string }> {
|
|
52
|
+
return { json: JSON.stringify(await this.appService.findTodos()) };
|
|
53
|
+
}
|
|
54
|
+
{{else}}
|
|
55
|
+
@MessagePattern("todo.create")
|
|
56
|
+
createTodo(data: { title: string }) {
|
|
57
|
+
return this.appService.createTodo(data);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@MessagePattern("todo.list")
|
|
61
|
+
listTodos() {
|
|
62
|
+
return this.appService.findTodos();
|
|
63
|
+
}
|
|
64
|
+
{{/if}}
|
|
65
|
+
{{/if}}
|
|
66
|
+
|
|
43
67
|
@Get()
|
|
44
68
|
getHello(): string {
|
|
45
69
|
return this.appService.getHello();
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { Module } from "@nestjs/common";
|
|
2
|
+
{{#if hasRateLimiting}}
|
|
3
|
+
import { APP_GUARD } from "@nestjs/core";
|
|
4
|
+
import { ThrottlerModule } from "@nestjs/throttler";
|
|
5
|
+
{{/if}}
|
|
2
6
|
{{#if (or hasDatabase hasOrm)}}
|
|
3
7
|
import { DbModule } from "./database/db.module.js";
|
|
4
8
|
import { env } from "./config/env.js";
|
|
@@ -9,6 +13,27 @@ import { AuthModule } from "./auth/auth.module.js";
|
|
|
9
13
|
|
|
10
14
|
import { AppController } from "./app.controller.js";
|
|
11
15
|
import { AppService } from "./app.service.js";
|
|
16
|
+
{{#if hasTrpc}}
|
|
17
|
+
import { TRPCModule } from "nestjs-trpc";
|
|
18
|
+
import { AppRouterClass as AppRouter } from "./app.router.js";
|
|
19
|
+
import { AppContext } from "./libs/trpc/context.js";
|
|
20
|
+
import { AppErrorHandler } from "./libs/trpc/error.handler.js";
|
|
21
|
+
{{#if hasRateLimiting}}
|
|
22
|
+
import { RateLimitTRPCMiddleware } from "./libs/middlewares/rate-limit.trpc.middleware.js";
|
|
23
|
+
{{/if}}
|
|
24
|
+
{{#if hasTodoExample}}
|
|
25
|
+
import { TodoRouter } from "./api/todo/todo.router.js";
|
|
26
|
+
{{/if}}
|
|
27
|
+
{{/if}}
|
|
28
|
+
{{#if hasRateLimiting}}
|
|
29
|
+
import { HttpThrottlerGuard } from "./http-throttler.guard.js";
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if (and hasRest hasTodoExample)}}
|
|
32
|
+
import { TodoModule } from "./api/todo/todo.module.js";
|
|
33
|
+
{{/if}}
|
|
34
|
+
{{#if hasHealthCheck}}
|
|
35
|
+
import { HealthModule } from "./health/health.module.js";
|
|
36
|
+
{{/if}}
|
|
12
37
|
|
|
13
38
|
@Module({
|
|
14
39
|
controllers: [AppController],
|
|
@@ -18,13 +43,48 @@ import { AppService } from "./app.service.js";
|
|
|
18
43
|
{{#if hasPostgres}}postgresUrl: env.POSTGRES_URL,{{/if}}
|
|
19
44
|
{{#if hasMysql}}mysqlUrl: env.MYSQL_URL,{{/if}}
|
|
20
45
|
{{#if hasSqlite}}sqlitePath: env.SQLITE_PATH,{{/if}}
|
|
46
|
+
{{#if hasSqlserver}}sqlserver: { database: env.SQLSERVER_DATABASE, options: { encrypt: env.SQLSERVER_ENCRYPT, trustServerCertificate: env.SQLSERVER_TRUST_SERVER_CERTIFICATE }, password: env.SQLSERVER_PASSWORD, port: env.SQLSERVER_PORT, server: env.SQLSERVER_HOST, user: env.SQLSERVER_USER },{{/if}}
|
|
21
47
|
{{#if hasMongodb}}mongodbUrl: env.MONGODB_URL,{{/if}}
|
|
22
48
|
}),
|
|
23
49
|
{{/if}}
|
|
24
50
|
{{#if (or (eq auth "better-auth") (eq auth "better-auth:stateless"))}}
|
|
25
51
|
AuthModule,
|
|
26
52
|
{{/if}}
|
|
53
|
+
{{#if hasTrpc}}
|
|
54
|
+
TRPCModule.forRoot({
|
|
55
|
+
context: AppContext,
|
|
56
|
+
{{#if hasRateLimiting}}
|
|
57
|
+
globalMiddlewares: [RateLimitTRPCMiddleware],
|
|
58
|
+
{{/if}}
|
|
59
|
+
onError: AppErrorHandler,
|
|
60
|
+
}),
|
|
61
|
+
{{/if}}
|
|
62
|
+
{{#if hasRateLimiting}}
|
|
63
|
+
ThrottlerModule.forRoot([{ limit: 60, ttl: 60_000 }]),
|
|
64
|
+
{{/if}}
|
|
65
|
+
{{#if (and hasRest hasTodoExample)}}
|
|
66
|
+
TodoModule,
|
|
67
|
+
{{/if}}
|
|
68
|
+
{{#if hasHealthCheck}}
|
|
69
|
+
HealthModule,
|
|
70
|
+
{{/if}}
|
|
71
|
+
],
|
|
72
|
+
providers: [
|
|
73
|
+
AppService,
|
|
74
|
+
{{#if hasTrpc}}
|
|
75
|
+
AppContext,
|
|
76
|
+
AppErrorHandler,
|
|
77
|
+
AppRouter,
|
|
78
|
+
{{#if hasRateLimiting}}
|
|
79
|
+
RateLimitTRPCMiddleware,
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if hasTodoExample}}
|
|
82
|
+
TodoRouter,
|
|
83
|
+
{{/if}}
|
|
84
|
+
{{/if}}
|
|
85
|
+
{{#if hasRateLimiting}}
|
|
86
|
+
{ provide: APP_GUARD, useClass: HttpThrottlerGuard },
|
|
87
|
+
{{/if}}
|
|
27
88
|
],
|
|
28
|
-
providers: [AppService],
|
|
29
89
|
})
|
|
30
90
|
export class AppModule {}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Injectable } from "@nestjs/common";
|
|
2
|
-
{{#if (
|
|
3
|
-
import {
|
|
2
|
+
{{#if (and hasDatabase hasTodoExample)}}
|
|
3
|
+
import { RpcException } from "@nestjs/microservices";
|
|
4
|
+
import { TodoService } from "./api/todo/todo.service.js";
|
|
4
5
|
{{/if}}
|
|
5
6
|
|
|
6
7
|
@Injectable()
|
|
@@ -26,8 +27,19 @@ export class AppService {
|
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
{{/unless}}
|
|
29
|
-
{{#if (
|
|
30
|
-
constructor(private readonly
|
|
30
|
+
{{#if (and hasDatabase hasTodoExample)}}
|
|
31
|
+
constructor(private readonly todos: TodoService) {}
|
|
32
|
+
|
|
33
|
+
createTodo(data: { title: string }) {
|
|
34
|
+
if (typeof data?.title !== "string" || data.title.trim().length === 0) {
|
|
35
|
+
throw new RpcException({ code: 3, message: "A non-empty title is required" });
|
|
36
|
+
}
|
|
37
|
+
return this.todos.create({ completed: false, title: data.title });
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
findTodos() {
|
|
41
|
+
return this.todos.findAll();
|
|
42
|
+
}
|
|
31
43
|
|
|
32
44
|
{{/if}}
|
|
33
45
|
getHello(): string {
|
package/dist/templates/single-project/architecture/nest-microservice/src/http-throttler.guard.ts.hbs
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import type { ExecutionContext } from "@nestjs/common";
|
|
3
|
+
import { ThrottlerGuard } from "@nestjs/throttler";
|
|
4
|
+
|
|
5
|
+
@Injectable()
|
|
6
|
+
export class HttpThrottlerGuard extends ThrottlerGuard {
|
|
7
|
+
canActivate(context: ExecutionContext): Promise<boolean> {
|
|
8
|
+
if (context.getType() !== "http") {
|
|
9
|
+
return Promise.resolve(true);
|
|
10
|
+
}
|
|
11
|
+
return super.canActivate(context);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,7 +1,15 @@
|
|
|
1
|
+
{{#if (includes microservices "grpc")}}
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
{{/if}}
|
|
1
4
|
{{#if (eq httpProvider "fastify")}}
|
|
2
5
|
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
|
|
3
6
|
{{/if}}
|
|
7
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
4
8
|
import { Logger } from "@nestjs/common";
|
|
9
|
+
import { ZodValidationPipe } from "nestjs-zod";
|
|
10
|
+
{{else}}
|
|
11
|
+
import { Logger, StandardSchemaValidationPipe } from "@nestjs/common";
|
|
12
|
+
{{/if}}
|
|
5
13
|
import { NestFactory } from "@nestjs/core";
|
|
6
14
|
import { Transport } from "@nestjs/microservices";
|
|
7
15
|
import type { MicroserviceOptions } from "@nestjs/microservices";
|
|
@@ -22,9 +30,20 @@ import { AuthService } from "@thallesp/nestjs-better-auth";
|
|
|
22
30
|
{{/if}}
|
|
23
31
|
|
|
24
32
|
async function bootstrap() {
|
|
25
|
-
const
|
|
33
|
+
const trustedProxyIps = env.TRUSTED_PROXY_IPS.split(",").map((ip) => ip.trim()).filter(Boolean);
|
|
34
|
+
const app = await NestFactory.create{{#if (eq httpProvider "fastify")}}<NestFastifyApplication>(AppModule, new FastifyAdapter({ trustProxy: trustedProxyIps })){{else}}(AppModule){{/if}};
|
|
35
|
+
{{#unless (eq httpProvider "fastify")}}
|
|
36
|
+
if (trustedProxyIps.length > 0) {
|
|
37
|
+
app.getHttpAdapter().getInstance().set("trust proxy", trustedProxyIps);
|
|
38
|
+
}
|
|
39
|
+
{{/unless}}
|
|
26
40
|
app.enableCors({ origin: env.CORS_ORIGIN });
|
|
27
41
|
app.setGlobalPrefix("api");
|
|
42
|
+
{{#if (includes addons "nestjs-zod")}}
|
|
43
|
+
app.useGlobalPipes(new ZodValidationPipe());
|
|
44
|
+
{{else}}
|
|
45
|
+
app.useGlobalPipes(new StandardSchemaValidationPipe());
|
|
46
|
+
{{/if}}
|
|
28
47
|
app.enableShutdownHooks();
|
|
29
48
|
|
|
30
49
|
app.connectMicroservice<MicroserviceOptions>({
|
|
@@ -34,7 +53,7 @@ async function bootstrap() {
|
|
|
34
53
|
{{/if}}
|
|
35
54
|
{{#if (includes microservices "grpc")}}
|
|
36
55
|
package: "app",
|
|
37
|
-
protoPath: "proto/app.proto",
|
|
56
|
+
protoPath: fileURLToPath(new URL("proto/app.proto", import.meta.url)),
|
|
38
57
|
url: env.GRPC_URL ?? "0.0.0.0:5000",
|
|
39
58
|
{{/if}}
|
|
40
59
|
{{#if (includes microservices "rabbitmq")}}
|
|
@@ -78,8 +97,8 @@ async function bootstrap() {
|
|
|
78
97
|
{{/if}}
|
|
79
98
|
{{#if (includes apis "trpc")}}
|
|
80
99
|
trpc: {
|
|
81
|
-
routerFilePath: "./src/trpc/router.ts",
|
|
82
100
|
pathPrefix: "/trpc",
|
|
101
|
+
routerFilePath: "./{{trpcGeneratePath}}/server.ts",
|
|
83
102
|
},
|
|
84
103
|
{{/if}}
|
|
85
104
|
zod: {
|
|
@@ -88,10 +107,10 @@ async function bootstrap() {
|
|
|
88
107
|
},
|
|
89
108
|
title: "{{projectNamePascalCase}} API",
|
|
90
109
|
version: "1.0.0",
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
pageTitle: "{{projectNamePascalCase}} API Docs",
|
|
110
|
+
}),
|
|
111
|
+
pageTitle: "{{projectNamePascalCase}} API Docs",
|
|
94
112
|
theme: "default",
|
|
113
|
+
{{#if (eq httpProvider "fastify")}}withFastify: true,{{/if}}
|
|
95
114
|
}),
|
|
96
115
|
);
|
|
97
116
|
{{else}}
|
|
@@ -106,7 +125,7 @@ async function bootstrap() {
|
|
|
106
125
|
{{/if}}
|
|
107
126
|
{{#if (includes apis "trpc")}}
|
|
108
127
|
trpc: {
|
|
109
|
-
routerFilePath: "./
|
|
128
|
+
routerFilePath: "./{{trpcGeneratePath}}/server.ts",
|
|
110
129
|
pathPrefix: "/trpc",
|
|
111
130
|
},
|
|
112
131
|
{{/if}}
|
|
@@ -1,102 +1,22 @@
|
|
|
1
1
|
import type { INestApplication } from "@nestjs/common";
|
|
2
|
-
|
|
3
|
-
import
|
|
4
|
-
import { Test } from "@nestjs/testing";
|
|
5
|
-
{{#unless (includes microservices "grpc")}}
|
|
6
|
-
import { setTimeout as delay } from "node:timers/promises";
|
|
7
|
-
import request from "supertest";
|
|
8
|
-
{{/unless}}
|
|
9
|
-
import { firstValueFrom } from "rxjs";
|
|
10
|
-
{{#if (includes microservices "grpc")}}
|
|
11
|
-
import type { Observable } from "rxjs";
|
|
2
|
+
{{#if (eq httpProvider "fastify")}}
|
|
3
|
+
import { FastifyAdapter, NestFastifyApplication } from "@nestjs/platform-fastify";
|
|
12
4
|
{{/if}}
|
|
5
|
+
import { Test } from "@nestjs/testing";
|
|
13
6
|
import { afterAll, expect, it } from "vitest";
|
|
14
7
|
|
|
15
8
|
import { AppModule } from "../src/app.module.js";
|
|
16
|
-
import { env } from "../src/config/env.js";
|
|
17
|
-
|
|
18
|
-
const transport = {{#if (includes microservices "redis")}}Transport.REDIS{{else if (includes microservices "mqtt")}}Transport.MQTT{{else if (includes microservices "nats")}}Transport.NATS{{else if (includes microservices "rabbitmq")}}Transport.RMQ{{else if (includes microservices "kafka")}}Transport.KAFKA{{else if (includes microservices "grpc")}}Transport.GRPC{{else}}Transport.TCP{{/if}};
|
|
19
|
-
|
|
20
|
-
const options = {
|
|
21
|
-
{{#if (includes microservices "kafka")}}
|
|
22
|
-
client: { brokers: [env.KAFKA_BROKER] },
|
|
23
|
-
consumer: { groupId: "ping-consumer" },
|
|
24
|
-
{{/if}}
|
|
25
|
-
{{#if (includes microservices "grpc")}}
|
|
26
|
-
package: "app",
|
|
27
|
-
protoPath: "proto/app.proto",
|
|
28
|
-
url: env.GRPC_URL,
|
|
29
|
-
{{/if}}
|
|
30
|
-
{{#if (includes microservices "rabbitmq")}}
|
|
31
|
-
queue: "ping",
|
|
32
|
-
queueOptions: { durable: false },
|
|
33
|
-
urls: [env.RABBITMQ_URL],
|
|
34
|
-
{{/if}}
|
|
35
|
-
{{#if (includes microservices "redis")}}
|
|
36
|
-
host: new URL(env.REDIS_URL).hostname,
|
|
37
|
-
port: Number(new URL(env.REDIS_URL).port || 6379),
|
|
38
|
-
{{/if}}
|
|
39
|
-
{{#if (includes microservices "nats")}}
|
|
40
|
-
servers: [env.NATS_URL],
|
|
41
|
-
{{/if}}
|
|
42
|
-
{{#if (includes microservices "mqtt")}}
|
|
43
|
-
url: env.MQTT_URL,
|
|
44
|
-
{{/if}}
|
|
45
|
-
};
|
|
46
9
|
|
|
47
10
|
let app: INestApplication;
|
|
48
|
-
const client{{#if (includes microservices "grpc")}}: ClientGrpc = ClientProxyFactory.create({ options, transport } as MicroserviceOptions) as unknown as ClientGrpc;{{else if (includes microservices "kafka")}}: ClientKafka = ClientProxyFactory.create({ options, transport } as MicroserviceOptions) as ClientKafka;{{else}}: ClientProxy = ClientProxyFactory.create({ options, transport } as MicroserviceOptions);{{/if}}
|
|
49
11
|
|
|
50
|
-
it("
|
|
12
|
+
it("serves the generated HTTP application", async () => {
|
|
51
13
|
const module = await Test.createTestingModule({ imports: [AppModule] }).compile();
|
|
52
|
-
app = module.createNestApplication();
|
|
53
|
-
app.connectMicroservice<MicroserviceOptions>({ options, transport } as MicroserviceOptions);
|
|
14
|
+
app = module.createNestApplication{{#if (eq httpProvider "fastify")}}<NestFastifyApplication>(new FastifyAdapter()){{else}}(){{/if}};
|
|
54
15
|
app.setGlobalPrefix("api");
|
|
55
|
-
await app.startAllMicroservices();
|
|
56
16
|
await app.init();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
client.subscribeToResponseOf("log");
|
|
60
|
-
{{/if}}
|
|
61
|
-
{{#unless (includes microservices "grpc")}}
|
|
62
|
-
{{#if (includes microservices "kafka")}}
|
|
63
|
-
try {
|
|
64
|
-
await client.connect();
|
|
65
|
-
} catch {
|
|
66
|
-
await delay(1000);
|
|
67
|
-
await client.connect();
|
|
68
|
-
}
|
|
69
|
-
{{else}}
|
|
70
|
-
await client.connect();
|
|
71
|
-
{{/if}}
|
|
72
|
-
{{/unless}}
|
|
73
|
-
{{#if (includes microservices "grpc")}}
|
|
74
|
-
const service = client.getService<{
|
|
75
|
-
ping: (request: Record<string, never>) => Observable<{ message: string }>;
|
|
76
|
-
log: (request: { id: string; source: string; payload: string }) => Observable<{ id: string; source: string; payload: string }>;
|
|
77
|
-
}>("AppService");
|
|
78
|
-
await expect(firstValueFrom(service.ping({}))).resolves.toEqual({ message: "pong" });
|
|
79
|
-
const event = { id: "event-1", payload: "healthy", source: "scenario" };
|
|
80
|
-
await expect(firstValueFrom(service.log(event))).resolves.toEqual(event);
|
|
81
|
-
{{else}}
|
|
82
|
-
await expect(firstValueFrom(client.send<string, Record<string, never>>("ping", {}))).resolves.toBe("pong");
|
|
83
|
-
const event = { id: "event-1", payload: { healthy: true }, source: "scenario" };
|
|
84
|
-
await expect(firstValueFrom(client.send("log", event))).resolves.toEqual({ received: event });
|
|
85
|
-
const auditEvent = {
|
|
86
|
-
id: "audit-1",
|
|
87
|
-
payload: { healthy: true },
|
|
88
|
-
source: "scenario",
|
|
89
|
-
};
|
|
90
|
-
await firstValueFrom(client.emit("audit", auditEvent));
|
|
91
|
-
await delay(250);
|
|
92
|
-
const auditResponse = await request(app.getHttpServer())
|
|
93
|
-
.get(`/api/events/${auditEvent.id}`)
|
|
94
|
-
.expect(200);
|
|
95
|
-
expect(auditResponse.body).toEqual(auditEvent);
|
|
96
|
-
{{/if}}
|
|
97
|
-
}, 60_000);
|
|
17
|
+
expect(app.getHttpServer()).toBeDefined();
|
|
18
|
+
});
|
|
98
19
|
|
|
99
20
|
afterAll(async () => {
|
|
100
21
|
await app?.close();
|
|
101
|
-
client.close();
|
|
102
22
|
});
|
|
@@ -35,9 +35,15 @@ export const env = createEnv({
|
|
|
35
35
|
{{#if (or (includes microservices "redis") (includes microservices "mqtt") (includes microservices "nats") (includes microservices "rabbitmq") (includes microservices "kafka") (includes microservices "grpc"))}}
|
|
36
36
|
MICROSERVICE_PORT: z.string().transform(Number).default(3001),
|
|
37
37
|
{{/if}}
|
|
38
|
+
{{#if hasMongodb}}
|
|
39
|
+
MONGODB_URL: z.url(),
|
|
40
|
+
{{/if}}
|
|
38
41
|
{{#if (includes microservices "mqtt")}}
|
|
39
42
|
MQTT_URL: z.url().default("mqtt://127.0.0.1:1883"),
|
|
40
43
|
{{/if}}
|
|
44
|
+
{{#if hasMysql}}
|
|
45
|
+
MYSQL_URL: z.url(),
|
|
46
|
+
{{/if}}
|
|
41
47
|
{{#if (includes microservices "nats")}}
|
|
42
48
|
NATS_URL: z.url().default("nats://127.0.0.1:4222"),
|
|
43
49
|
{{/if}}
|
|
@@ -48,34 +54,28 @@ export const env = createEnv({
|
|
|
48
54
|
.string()
|
|
49
55
|
.transform(Number)
|
|
50
56
|
.default(3000),
|
|
57
|
+
{{#if hasPostgres}}
|
|
58
|
+
POSTGRES_URL: z.url(),
|
|
59
|
+
{{/if}}
|
|
51
60
|
{{#if (includes microservices "rabbitmq")}}
|
|
52
61
|
RABBITMQ_URL: z.url().default("amqp://127.0.0.1:5672"),
|
|
53
62
|
{{/if}}
|
|
54
63
|
{{#if (includes microservices "redis")}}
|
|
55
64
|
REDIS_URL: z.url().default("redis://127.0.0.1:6379"),
|
|
56
65
|
{{/if}}
|
|
57
|
-
TRUSTED_PROXY_IPS: z.string().default("{{#each trustedProxyIps}}{{#unless @first}},{{/unless}}{{this}}{{/each}}"),
|
|
58
|
-
{{#if hasPostgres}}
|
|
59
|
-
POSTGRES_URL: z.url(),
|
|
60
|
-
{{/if}}
|
|
61
|
-
{{#if hasMysql}}
|
|
62
|
-
MYSQL_URL: z.url(),
|
|
63
|
-
{{/if}}
|
|
64
66
|
{{#if hasSqlite}}
|
|
65
67
|
SQLITE_PATH: z.string().default("sqlite.db"),
|
|
66
68
|
{{/if}}
|
|
67
69
|
{{#if hasSqlserver}}
|
|
68
|
-
SQLSERVER_HOST: z.string().default("localhost"),
|
|
69
|
-
SQLSERVER_PORT: z.string().transform(Number).default(1433),
|
|
70
70
|
SQLSERVER_DATABASE: z.string().default("{{projectNameKebab}}_db"),
|
|
71
|
-
SQLSERVER_USER: z.string(),
|
|
72
|
-
SQLSERVER_PASSWORD: z.string(),
|
|
73
71
|
SQLSERVER_ENCRYPT: z.string().transform((value) => value !== "false").default(true),
|
|
72
|
+
SQLSERVER_HOST: z.string().default("localhost"),
|
|
73
|
+
SQLSERVER_PASSWORD: z.string(),
|
|
74
|
+
SQLSERVER_PORT: z.string().transform(Number).default(1433),
|
|
74
75
|
SQLSERVER_TRUST_SERVER_CERTIFICATE: z.string().transform((value) => value === "true").default(false),
|
|
76
|
+
SQLSERVER_USER: z.string(),
|
|
75
77
|
{{/if}}
|
|
76
|
-
{{#
|
|
77
|
-
MONGODB_URL: z.url(),
|
|
78
|
-
{{/if}}
|
|
78
|
+
TRUSTED_PROXY_IPS: z.string().default("{{#each trustedProxyIps}}{{#unless @first}},{{/unless}}{{this}}{{/each}}"),
|
|
79
79
|
{{#if hasGraphql}}
|
|
80
80
|
GRAPHQL_PLAYGROUND: z
|
|
81
81
|
.string()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nest-arch/tui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Interactive terminal UI for generating NestJS projects",
|
|
6
6
|
"keywords": [
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"handlebars": "^4.7.8",
|
|
39
39
|
"ink": "^5.0.1",
|
|
40
40
|
"ink-text-input": "^6.0.0",
|
|
41
|
+
"jsonc-parser": "^3.3.1",
|
|
41
42
|
"open": "^11.0.0",
|
|
42
43
|
"react": "^18.3.1",
|
|
43
44
|
"semver": "^7.8.5",
|
|
@@ -45,15 +46,15 @@
|
|
|
45
46
|
"zod": "^4.1.13"
|
|
46
47
|
},
|
|
47
48
|
"devDependencies": {
|
|
49
|
+
"@nest-arch/core": "0.4.3",
|
|
50
|
+
"@nest-arch/env": "0.0.0",
|
|
51
|
+
"@nest-arch/shared": "0.0.0",
|
|
48
52
|
"@types/react": "^18.3.12",
|
|
49
53
|
"@types/semver": "^7.8.0",
|
|
50
54
|
"ink-testing-library": "^4.0.0",
|
|
51
55
|
"pkgroll": "^2.5.2",
|
|
52
56
|
"tsx": "^4.19.2",
|
|
53
|
-
"vitest": "^4.1.7"
|
|
54
|
-
"@nest-arch/env": "0.0.0",
|
|
55
|
-
"@nest-arch/core": "0.4.3",
|
|
56
|
-
"@nest-arch/shared": "0.0.0"
|
|
57
|
+
"vitest": "^4.1.7"
|
|
57
58
|
},
|
|
58
59
|
"peerDependencies": {
|
|
59
60
|
"typescript": "^5"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
var o="0.4.6",O={version:o};const s="Nest Arch",A=`v${O.version}`,n="Build production-ready NestJS projects.",t="#e54545",c="#A0A0A0",R="#6B6B6B",C="#E5E5E5",E="#61AFEF",_="#3A3A3A",e="#7FD99A",r="#E8C468",L="#e96142ff";export{s as APP_NAME,n as APP_TAGLINE,A as APP_VERSION,E as COLOR_ACCENT,c as COLOR_DIM,R as COLOR_DIMMER,_ as COLOR_DIVIDER,C as COLOR_FG,t as COLOR_RED,e as COLOR_SUCCESS,r as COLOR_WARM,L as COLOR_WARM_SECONDARY};
|