@node-initializr/generator 0.1.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.
Files changed (152) hide show
  1. package/dist/generate.d.ts +12 -0
  2. package/dist/generate.js +77 -0
  3. package/dist/index.d.ts +4 -0
  4. package/dist/index.js +14 -0
  5. package/dist/template-engine.d.ts +24 -0
  6. package/dist/template-engine.js +472 -0
  7. package/dist/templates/arch-clean/express/src/application/use-cases/get-users.use-case.hbs +39 -0
  8. package/dist/templates/arch-clean/express/src/config/env.hbs +4 -0
  9. package/dist/templates/arch-clean/express/src/domain/entities/user.entity.hbs +7 -0
  10. package/dist/templates/arch-clean/express/src/index.hbs +66 -0
  11. package/dist/templates/arch-clean/express/src/infrastructure/http/health.routes.hbs +7 -0
  12. package/dist/templates/arch-clean/express/src/infrastructure/http/users.routes.hbs +9 -0
  13. package/dist/templates/arch-clean/express/src/shared/errors/app.error.hbs +5 -0
  14. package/dist/templates/arch-clean/fastify/src/application/use-cases/get-users.use-case.hbs +39 -0
  15. package/dist/templates/arch-clean/fastify/src/domain/entities/user.entity.hbs +7 -0
  16. package/dist/templates/arch-clean/fastify/src/index.hbs +53 -0
  17. package/dist/templates/arch-clean/fastify/src/infrastructure/http/routes.hbs +8 -0
  18. package/dist/templates/arch-clean/fastify/src/shared/errors/app.error.hbs +5 -0
  19. package/dist/templates/arch-clean/nestjs/src/app.module.ts.hbs +58 -0
  20. package/dist/templates/arch-clean/nestjs/src/application/use-cases/get-users.use-case.ts.hbs +14 -0
  21. package/dist/templates/arch-clean/nestjs/src/config/config.module.ts.hbs +4 -0
  22. package/dist/templates/arch-clean/nestjs/src/domain/entities/user.entity.ts.hbs +7 -0
  23. package/dist/templates/arch-clean/nestjs/src/domain/repositories/user.repository.ts.hbs +7 -0
  24. package/dist/templates/arch-clean/nestjs/src/infrastructure/http/health.controller.ts.hbs +11 -0
  25. package/dist/templates/arch-clean/nestjs/src/infrastructure/http/users.controller.ts.hbs +22 -0
  26. package/dist/templates/arch-clean/nestjs/src/infrastructure/persistence/drizzle-user.repository.ts.hbs +15 -0
  27. package/dist/templates/arch-clean/nestjs/src/infrastructure/persistence/in-memory-user.repository.ts.hbs +10 -0
  28. package/dist/templates/arch-clean/nestjs/src/infrastructure/persistence/prisma-user.repository.ts.hbs +14 -0
  29. package/dist/templates/arch-clean/nestjs/src/infrastructure/persistence/sequelize-user.repository.ts.hbs +18 -0
  30. package/dist/templates/arch-clean/nestjs/src/infrastructure/persistence/typeorm-user.repository.ts.hbs +19 -0
  31. package/dist/templates/arch-clean/nestjs/src/infrastructure/prisma/prisma.module.ts.hbs +6 -0
  32. package/dist/templates/arch-clean/nestjs/src/infrastructure/prisma/prisma.service.ts.hbs +8 -0
  33. package/dist/templates/arch-clean/nestjs/src/main.ts.hbs +21 -0
  34. package/dist/templates/arch-clean/nestjs/src/shared/errors/app.error.ts.hbs +9 -0
  35. package/dist/templates/arch-clean/nestjs/tests/health.spec.ts.hbs +17 -0
  36. package/dist/templates/arch-modular/express/src/index.hbs +46 -0
  37. package/dist/templates/arch-modular/express/src/infra/database.hbs +3 -0
  38. package/dist/templates/arch-modular/express/src/modules/health/health.routes.hbs +7 -0
  39. package/dist/templates/arch-modular/express/src/modules/users/users.routes.hbs +55 -0
  40. package/dist/templates/arch-modular/express/src/shared/constants.hbs +1 -0
  41. package/dist/templates/arch-modular/fastify/src/index.hbs +33 -0
  42. package/dist/templates/arch-modular/fastify/src/infra/database.hbs +3 -0
  43. package/dist/templates/arch-modular/fastify/src/modules/health/health.routes.hbs +9 -0
  44. package/dist/templates/arch-modular/fastify/src/modules/users/users.routes.hbs +48 -0
  45. package/dist/templates/arch-modular/fastify/src/shared/constants.hbs +1 -0
  46. package/dist/templates/arch-modular/nestjs/src/app.module.ts.hbs +63 -0
  47. package/dist/templates/arch-modular/nestjs/src/config/config.module.ts.hbs +4 -0
  48. package/dist/templates/arch-modular/nestjs/src/infra/prisma/prisma.module.ts.hbs +9 -0
  49. package/dist/templates/arch-modular/nestjs/src/infra/prisma/prisma.service.ts.hbs +13 -0
  50. package/dist/templates/arch-modular/nestjs/src/main.ts.hbs +28 -0
  51. package/dist/templates/arch-modular/nestjs/src/modules/health/health.controller.ts.hbs +17 -0
  52. package/dist/templates/arch-modular/nestjs/src/modules/health/health.module.ts.hbs +7 -0
  53. package/dist/templates/arch-modular/nestjs/src/modules/users/users.controller.ts.hbs +24 -0
  54. package/dist/templates/arch-modular/nestjs/src/modules/users/users.module.ts.hbs +10 -0
  55. package/dist/templates/arch-modular/nestjs/src/modules/users/users.service.ts.hbs +60 -0
  56. package/dist/templates/arch-modular/nestjs/src/shared/constants.ts.hbs +1 -0
  57. package/dist/templates/arch-modular/nestjs/tests/health.spec.ts.hbs +16 -0
  58. package/dist/templates/arch-mvc/express/src/controllers/health.controller.hbs +7 -0
  59. package/dist/templates/arch-mvc/express/src/controllers/users.controller.hbs +10 -0
  60. package/dist/templates/arch-mvc/express/src/index.hbs +60 -0
  61. package/dist/templates/arch-mvc/express/src/models/user.model.hbs +7 -0
  62. package/dist/templates/arch-mvc/express/src/services/users.service.hbs +39 -0
  63. package/dist/templates/arch-mvc/fastify/src/controllers/users.controller.hbs +9 -0
  64. package/dist/templates/arch-mvc/fastify/src/index.hbs +53 -0
  65. package/dist/templates/arch-mvc/fastify/src/models/user.model.hbs +7 -0
  66. package/dist/templates/arch-mvc/fastify/src/services/users.service.hbs +39 -0
  67. package/dist/templates/arch-mvc/nestjs/src/app.module.ts.hbs +44 -0
  68. package/dist/templates/arch-mvc/nestjs/src/config/config.module.ts.hbs +4 -0
  69. package/dist/templates/arch-mvc/nestjs/src/controllers/health.controller.ts.hbs +11 -0
  70. package/dist/templates/arch-mvc/nestjs/src/controllers/users.controller.ts.hbs +22 -0
  71. package/dist/templates/arch-mvc/nestjs/src/infra/prisma/prisma.module.ts.hbs +6 -0
  72. package/dist/templates/arch-mvc/nestjs/src/infra/prisma/prisma.service.ts.hbs +8 -0
  73. package/dist/templates/arch-mvc/nestjs/src/main.ts.hbs +21 -0
  74. package/dist/templates/arch-mvc/nestjs/src/models/user.model.ts.hbs +7 -0
  75. package/dist/templates/arch-mvc/nestjs/src/services/users.service.ts.hbs +61 -0
  76. package/dist/templates/arch-mvc/nestjs/tests/health.spec.ts.hbs +17 -0
  77. package/dist/templates/base-express/.env.example.hbs +21 -0
  78. package/dist/templates/base-express/.gitignore.hbs +6 -0
  79. package/dist/templates/base-express/README.md.hbs +10 -0
  80. package/dist/templates/base-express/docker/Dockerfile.hbs +21 -0
  81. package/dist/templates/base-express/docker/docker-compose.yml.hbs +61 -0
  82. package/dist/templates/base-express/drizzle/drizzle.config.hbs +10 -0
  83. package/dist/templates/base-express/github-actions/ci.yml.hbs +40 -0
  84. package/dist/templates/base-express/package.json.hbs +54 -0
  85. package/dist/templates/base-express/prisma/schema.prisma.hbs +16 -0
  86. package/dist/templates/base-express/tests/health.test.hbs +8 -0
  87. package/dist/templates/base-express/tsconfig.json.hbs +13 -0
  88. package/dist/templates/base-fastify/.env.example.hbs +21 -0
  89. package/dist/templates/base-fastify/.gitignore.hbs +6 -0
  90. package/dist/templates/base-fastify/README.md.hbs +10 -0
  91. package/dist/templates/base-fastify/docker/Dockerfile.hbs +21 -0
  92. package/dist/templates/base-fastify/docker/docker-compose.yml.hbs +61 -0
  93. package/dist/templates/base-fastify/drizzle/drizzle.config.hbs +10 -0
  94. package/dist/templates/base-fastify/github-actions/ci.yml.hbs +40 -0
  95. package/dist/templates/base-fastify/package.json.hbs +50 -0
  96. package/dist/templates/base-fastify/prisma/schema.prisma.hbs +16 -0
  97. package/dist/templates/base-fastify/tests/health.test.hbs +8 -0
  98. package/dist/templates/base-fastify/tsconfig.json.hbs +13 -0
  99. package/dist/templates/base-nestjs/.env.example.hbs +24 -0
  100. package/dist/templates/base-nestjs/.gitignore.hbs +10 -0
  101. package/dist/templates/base-nestjs/README.md.hbs +46 -0
  102. package/dist/templates/base-nestjs/docker/Dockerfile.hbs +21 -0
  103. package/dist/templates/base-nestjs/docker/docker-compose.yml.hbs +69 -0
  104. package/dist/templates/base-nestjs/drizzle/drizzle.config.ts.hbs +10 -0
  105. package/dist/templates/base-nestjs/github-actions/ci.yml.hbs +38 -0
  106. package/dist/templates/base-nestjs/nest-cli.json.hbs +8 -0
  107. package/dist/templates/base-nestjs/package.json.hbs +65 -0
  108. package/dist/templates/base-nestjs/prisma/schema.prisma.hbs +16 -0
  109. package/dist/templates/base-nestjs/tsconfig.json.hbs +19 -0
  110. package/dist/templates/shared-express/src/infra/auth/clerk.middleware.hbs +12 -0
  111. package/dist/templates/shared-express/src/infra/auth/jwt.middleware.hbs +18 -0
  112. package/dist/templates/shared-express/src/infra/drizzle/client.hbs +18 -0
  113. package/dist/templates/shared-express/src/infra/drizzle/schema.hbs +22 -0
  114. package/dist/templates/shared-express/src/infra/prisma/client.hbs +15 -0
  115. package/dist/templates/shared-express/src/infra/sequelize/models/user.model.ts.hbs +22 -0
  116. package/dist/templates/shared-express/src/infra/sequelize/sequelize.ts.hbs +16 -0
  117. package/dist/templates/shared-express/src/infra/swagger/setup.hbs +19 -0
  118. package/dist/templates/shared-express/src/infra/typeorm/data-source.hbs +17 -0
  119. package/dist/templates/shared-express/src/infra/typeorm/entities/user.entity.hbs +25 -0
  120. package/dist/templates/shared-fastify/src/infra/auth/clerk.middleware.hbs +16 -0
  121. package/dist/templates/shared-fastify/src/infra/auth/jwt.middleware.hbs +14 -0
  122. package/dist/templates/shared-fastify/src/infra/drizzle/client.hbs +18 -0
  123. package/dist/templates/shared-fastify/src/infra/drizzle/schema.hbs +22 -0
  124. package/dist/templates/shared-fastify/src/infra/prisma/client.hbs +15 -0
  125. package/dist/templates/shared-fastify/src/infra/sequelize/models/user.model.ts.hbs +22 -0
  126. package/dist/templates/shared-fastify/src/infra/sequelize/sequelize.ts.hbs +16 -0
  127. package/dist/templates/shared-fastify/src/infra/swagger/setup.hbs +16 -0
  128. package/dist/templates/shared-fastify/src/infra/typeorm/data-source.hbs +17 -0
  129. package/dist/templates/shared-fastify/src/infra/typeorm/entities/user.entity.hbs +25 -0
  130. package/dist/templates/shared-nestjs/src/infra/auth/clerk/clerk-auth.guard.ts.hbs +25 -0
  131. package/dist/templates/shared-nestjs/src/infra/auth/jwt/jwt-auth.guard.ts.hbs +5 -0
  132. package/dist/templates/shared-nestjs/src/infra/auth/jwt/jwt.module.ts.hbs +17 -0
  133. package/dist/templates/shared-nestjs/src/infra/auth/jwt/jwt.strategy.ts.hbs +18 -0
  134. package/dist/templates/shared-nestjs/src/infra/drizzle/drizzle.module.ts.hbs +9 -0
  135. package/dist/templates/shared-nestjs/src/infra/drizzle/drizzle.service.ts.hbs +31 -0
  136. package/dist/templates/shared-nestjs/src/infra/drizzle/schema.ts.hbs +22 -0
  137. package/dist/templates/shared-nestjs/src/infra/sequelize/models/user.model.ts.hbs +22 -0
  138. package/dist/templates/shared-nestjs/src/infra/sequelize/sequelize.module.ts.hbs +18 -0
  139. package/dist/templates/shared-nestjs/src/infra/typeorm/entities/user.entity.ts.hbs +25 -0
  140. package/dist/templates/shared-nestjs/src/infra/typeorm/typeorm.module.ts.hbs +18 -0
  141. package/dist/templates/shared-nestjs/src/infrastructure/drizzle/drizzle.module.ts.hbs +9 -0
  142. package/dist/templates/shared-nestjs/src/infrastructure/drizzle/drizzle.service.ts.hbs +31 -0
  143. package/dist/templates/shared-nestjs/src/infrastructure/drizzle/schema.ts.hbs +22 -0
  144. package/dist/templates/shared-nestjs/src/infrastructure/sequelize/models/user.model.ts.hbs +22 -0
  145. package/dist/templates/shared-nestjs/src/infrastructure/sequelize/sequelize.module.ts.hbs +18 -0
  146. package/dist/templates/shared-nestjs/src/infrastructure/typeorm/entities/user.entity.ts.hbs +25 -0
  147. package/dist/templates/shared-nestjs/src/infrastructure/typeorm/typeorm.module.ts.hbs +18 -0
  148. package/dist/validate.d.ts +2 -0
  149. package/dist/validate.js +41 -0
  150. package/dist/zip.d.ts +2 -0
  151. package/dist/zip.js +20 -0
  152. package/package.json +37 -0
@@ -0,0 +1,66 @@
1
+ import 'dotenv/config';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+ import helmet from 'helmet';
5
+ import { GetUsersUseCase } from './application/use-cases/get-users.use-case.js';
6
+ {{#if useTypeorm}}
7
+ import { initTypeorm } from './infra/typeorm/data-source.js';
8
+ {{/if}}
9
+ {{#if useSequelize}}
10
+ import { initSequelize } from './infra/sequelize/sequelize.js';
11
+ {{/if}}
12
+ {{#if swagger}}
13
+ import { setupSwagger } from './infra/swagger/setup.js';
14
+ {{/if}}
15
+ {{#if useJwt}}
16
+ import { jwtMiddleware } from './infra/auth/jwt.middleware.js';
17
+ {{/if}}
18
+ {{#if useClerk}}
19
+ import { clerkAuth, requireClerkAuth } from './infra/auth/clerk.middleware.js';
20
+ {{/if}}
21
+
22
+ async function bootstrap() {
23
+ {{#if useTypeorm}}
24
+ await initTypeorm();
25
+ {{/if}}
26
+ {{#if useSequelize}}
27
+ await initSequelize();
28
+ {{/if}}
29
+
30
+ const app = express();
31
+ const getUsers = new GetUsersUseCase();
32
+
33
+ app.use(helmet());
34
+ app.use(cors());
35
+ app.use(express.json());
36
+ {{#if useClerk}}
37
+ app.use(clerkAuth);
38
+ {{/if}}
39
+ {{#if swagger}}
40
+ setupSwagger(app);
41
+ {{/if}}
42
+
43
+ app.get('/api/health', (_req, res) => {
44
+ res.json({ status: 'ok', service: '{{projectSlug}}', architecture: 'clean' });
45
+ });
46
+
47
+ const usersHandler = async (_req: express.Request, res: express.Response) => {
48
+ const users = await getUsers.execute();
49
+ res.json(users);
50
+ };
51
+
52
+ {{#if useJwt}}
53
+ app.get('/api/users', jwtMiddleware, usersHandler);
54
+ {{else}}
55
+ {{#if useClerk}}
56
+ app.get('/api/users', requireClerkAuth, usersHandler);
57
+ {{else}}
58
+ app.get('/api/users', usersHandler);
59
+ {{/if}}
60
+ {{/if}}
61
+
62
+ const port = process.env.PORT ?? 3000;
63
+ app.listen(port, () => console.log(`🚀 {{projectSlug}} (clean) on :${port}`));
64
+ }
65
+
66
+ bootstrap();
@@ -0,0 +1,7 @@
1
+ import { Router } from 'express';
2
+
3
+ export const healthRouter = Router();
4
+
5
+ healthRouter.get('/', (_req, res) => {
6
+ res.json({ status: 'ok', service: '{{projectSlug}}', architecture: 'clean' });
7
+ });
@@ -0,0 +1,9 @@
1
+ import { Router } from 'express';
2
+ import { GetUsersUseCase } from '../../application/use-cases/get-users.use-case.js';
3
+
4
+ const getUsers = new GetUsersUseCase();
5
+ export const usersRouter = Router();
6
+
7
+ usersRouter.get('/', async (_req, res) => {
8
+ res.json(await getUsers.execute());
9
+ });
@@ -0,0 +1,5 @@
1
+ export class AppError extends Error {
2
+ constructor(message: string, public readonly statusCode = 400) {
3
+ super(message);
4
+ }
5
+ }
@@ -0,0 +1,39 @@
1
+ import { User } from '../../domain/entities/user.entity.js';
2
+ {{#if usePrisma}}
3
+ import { prisma } from '../../infra/prisma/client.js';
4
+ {{/if}}
5
+ {{#if useTypeorm}}
6
+ import { AppDataSource } from '../../infra/typeorm/data-source.js';
7
+ import { UserEntity } from '../../infra/typeorm/entities/user.entity.js';
8
+ {{/if}}
9
+ {{#if useDrizzle}}
10
+ import { db } from '../../infra/drizzle/client.js';
11
+ import { users } from '../../infra/drizzle/schema.js';
12
+ {{/if}}
13
+ {{#if useSequelize}}
14
+ import { User } from '../../infra/sequelize/models/user.model.js';
15
+ {{/if}}
16
+
17
+ export class GetUsersUseCase {
18
+ async execute(): Promise<User[]> {
19
+ {{#if usePrisma}}
20
+ const rows = await prisma.user.findMany();
21
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
22
+ {{/if}}
23
+ {{#if useTypeorm}}
24
+ const rows = await AppDataSource.getRepository(UserEntity).find();
25
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
26
+ {{/if}}
27
+ {{#if useDrizzle}}
28
+ const rows = await db.select().from(users);
29
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
30
+ {{/if}}
31
+ {{#if useSequelize}}
32
+ const rows = await User.findAll();
33
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
34
+ {{/if}}
35
+ {{#unless hasRealOrm}}
36
+ return [new User('1', 'user@example.com', 'Demo User')];
37
+ {{/unless}}
38
+ }
39
+ }
@@ -0,0 +1,7 @@
1
+ export class User {
2
+ constructor(
3
+ public readonly id: string,
4
+ public readonly email: string,
5
+ public readonly name: string,
6
+ ) {}
7
+ }
@@ -0,0 +1,53 @@
1
+ import 'dotenv/config';
2
+ import Fastify from 'fastify';
3
+ import cors from '@fastify/cors';
4
+ import helmet from '@fastify/helmet';
5
+ import { GetUsersUseCase } from './application/use-cases/get-users.use-case.js';
6
+ {{#if useTypeorm}}
7
+ import { initTypeorm } from './infra/typeorm/data-source.js';
8
+ {{/if}}
9
+ {{#if useSequelize}}
10
+ import { initSequelize } from './infra/sequelize/sequelize.js';
11
+ {{/if}}
12
+ {{#if swagger}}
13
+ import { setupSwagger } from './infra/swagger/setup.js';
14
+ {{/if}}
15
+ {{#if useJwt}}
16
+ import { jwtMiddleware } from './infra/auth/jwt.middleware.js';
17
+ {{/if}}
18
+ {{#if useClerk}}
19
+ import { clerkMiddleware } from './infra/auth/clerk.middleware.js';
20
+ {{/if}}
21
+
22
+ {{#if useTypeorm}}
23
+ await initTypeorm();
24
+ {{/if}}
25
+ {{#if useSequelize}}
26
+ await initSequelize();
27
+ {{/if}}
28
+
29
+ const app = Fastify({ logger: true });
30
+ const getUsers = new GetUsersUseCase();
31
+
32
+ await app.register(cors);
33
+ await app.register(helmet);
34
+ {{#if swagger}}
35
+ await setupSwagger(app);
36
+ {{/if}}
37
+
38
+ app.get('/api/health', async () => ({
39
+ status: 'ok',
40
+ service: '{{projectSlug}}',
41
+ architecture: 'clean',
42
+ }));
43
+
44
+ app.get('/api/users', {
45
+ {{#if useJwt}}
46
+ preHandler: jwtMiddleware,
47
+ {{/if}}
48
+ {{#if useClerk}}
49
+ preHandler: clerkMiddleware,
50
+ {{/if}}
51
+ }, async () => getUsers.execute());
52
+
53
+ await app.listen({ port: Number(process.env.PORT ?? 3000), host: '0.0.0.0' });
@@ -0,0 +1,8 @@
1
+ import { FastifyInstance } from 'fastify';
2
+ import { GetUsersUseCase } from '../../application/use-cases/get-users.use-case.js';
3
+
4
+ export async function registerRoutes(app: FastifyInstance) {
5
+ const getUsers = new GetUsersUseCase();
6
+
7
+ app.get('/api/users', async () => getUsers.execute());
8
+ }
@@ -0,0 +1,5 @@
1
+ export class AppError extends Error {
2
+ constructor(message: string, public readonly statusCode = 400) {
3
+ super(message);
4
+ }
5
+ }
@@ -0,0 +1,58 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { ConfigModule } from './config/config.module';
3
+ import { GetUsersUseCase } from './application/use-cases/get-users.use-case';
4
+ import { HealthController } from './infrastructure/http/health.controller';
5
+ import { UsersController } from './infrastructure/http/users.controller';
6
+ import { USER_REPOSITORY } from './domain/repositories/user.repository';
7
+ {{#if usePrisma}}
8
+ import { PrismaModule } from './infrastructure/prisma/prisma.module';
9
+ import { PrismaUserRepository } from './infrastructure/persistence/prisma-user.repository';
10
+ {{/if}}
11
+ {{#if useTypeorm}}
12
+ import { TypeormModule } from './infrastructure/typeorm/typeorm.module';
13
+ import { TypeormUserRepository } from './infrastructure/persistence/typeorm-user.repository';
14
+ {{/if}}
15
+ {{#if useDrizzle}}
16
+ import { DrizzleModule } from './infrastructure/drizzle/drizzle.module';
17
+ import { DrizzleUserRepository } from './infrastructure/persistence/drizzle-user.repository';
18
+ {{/if}}
19
+ {{#if useSequelize}}
20
+ import { SequelizeModule } from './infrastructure/sequelize/sequelize.module';
21
+ import { SequelizeUserRepository } from './infrastructure/persistence/sequelize-user.repository';
22
+ {{/if}}
23
+ {{#unless hasRealOrm}}
24
+ import { InMemoryUserRepository } from './infrastructure/persistence/in-memory-user.repository';
25
+ {{/unless}}
26
+ {{#if useJwt}}
27
+ import { AuthJwtModule } from './infra/auth/jwt/jwt.module';
28
+ {{/if}}
29
+
30
+ @Module({
31
+ imports: [
32
+ ConfigModule,
33
+ {{#if usePrisma}}
34
+ PrismaModule,
35
+ {{/if}}
36
+ {{#if useTypeorm}}
37
+ TypeormModule,
38
+ {{/if}}
39
+ {{#if useDrizzle}}
40
+ DrizzleModule,
41
+ {{/if}}
42
+ {{#if useSequelize}}
43
+ SequelizeModule,
44
+ {{/if}}
45
+ {{#if useJwt}}
46
+ AuthJwtModule,
47
+ {{/if}}
48
+ ],
49
+ controllers: [HealthController, UsersController],
50
+ providers: [
51
+ GetUsersUseCase,
52
+ {
53
+ provide: USER_REPOSITORY,
54
+ useClass: {{#if usePrisma}}PrismaUserRepository{{/if}}{{#if useTypeorm}}TypeormUserRepository{{/if}}{{#if useDrizzle}}DrizzleUserRepository{{/if}}{{#if useSequelize}}SequelizeUserRepository{{/if}}{{#unless hasRealOrm}}InMemoryUserRepository{{/unless}},
55
+ },
56
+ ],
57
+ })
58
+ export class AppModule {}
@@ -0,0 +1,14 @@
1
+ import { Inject, Injectable } from '@nestjs/common';
2
+ import { User } from '../../domain/entities/user.entity';
3
+ import { USER_REPOSITORY, UserRepository } from '../../domain/repositories/user.repository';
4
+
5
+ @Injectable()
6
+ export class GetUsersUseCase {
7
+ constructor(
8
+ @Inject(USER_REPOSITORY) private readonly users: UserRepository,
9
+ ) {}
10
+
11
+ execute(): Promise<User[]> {
12
+ return this.users.findAll();
13
+ }
14
+ }
@@ -0,0 +1,4 @@
1
+ import { Module } from '@nestjs/common';
2
+
3
+ @Module({})
4
+ export class ConfigModule {}
@@ -0,0 +1,7 @@
1
+ export class User {
2
+ constructor(
3
+ public readonly id: string,
4
+ public readonly email: string,
5
+ public readonly name: string | null,
6
+ ) {}
7
+ }
@@ -0,0 +1,7 @@
1
+ import { User } from '../entities/user.entity';
2
+
3
+ export const USER_REPOSITORY = Symbol('USER_REPOSITORY');
4
+
5
+ export interface UserRepository {
6
+ findAll(): Promise<User[]>;
7
+ }
@@ -0,0 +1,11 @@
1
+ import { Controller, Get } from '@nestjs/common';
2
+ {{#if swagger}}import { ApiTags } from '@nestjs/swagger';{{/if}}
3
+
4
+ {{#if swagger}}@ApiTags('health'){{/if}}
5
+ @Controller('health')
6
+ export class HealthController {
7
+ @Get()
8
+ check() {
9
+ return { status: 'ok', service: '{{projectSlug}}', architecture: 'clean' };
10
+ }
11
+ }
@@ -0,0 +1,22 @@
1
+ import { Controller, Get{{#if useJwt}}, UseGuards{{/if}}{{#if useClerk}}, UseGuards{{/if}} } from '@nestjs/common';
2
+ import { GetUsersUseCase } from '../../application/use-cases/get-users.use-case';
3
+ {{#if swagger}}import { ApiTags } from '@nestjs/swagger';{{/if}}
4
+ {{#if useJwt}}
5
+ import { JwtAuthGuard } from '../../infra/auth/jwt/jwt-auth.guard';
6
+ {{/if}}
7
+ {{#if useClerk}}
8
+ import { ClerkAuthGuard } from '../../infra/auth/clerk/clerk-auth.guard';
9
+ {{/if}}
10
+
11
+ {{#if swagger}}@ApiTags('users'){{/if}}
12
+ @Controller('users')
13
+ {{#if useJwt}}@UseGuards(JwtAuthGuard){{/if}}
14
+ {{#if useClerk}}@UseGuards(ClerkAuthGuard){{/if}}
15
+ export class UsersController {
16
+ constructor(private readonly getUsers: GetUsersUseCase) {}
17
+
18
+ @Get()
19
+ findAll() {
20
+ return this.getUsers.execute();
21
+ }
22
+ }
@@ -0,0 +1,15 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { User } from '../../domain/entities/user.entity';
3
+ import { UserRepository } from '../../domain/repositories/user.repository';
4
+ import { DrizzleService } from '../drizzle/drizzle.service';
5
+ import { users } from '../drizzle/schema';
6
+
7
+ @Injectable()
8
+ export class DrizzleUserRepository implements UserRepository {
9
+ constructor(private readonly drizzle: DrizzleService) {}
10
+
11
+ async findAll(): Promise<User[]> {
12
+ const rows = await this.drizzle.db.select().from(users);
13
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { User } from '../../domain/entities/user.entity';
3
+ import { UserRepository } from '../../domain/repositories/user.repository';
4
+
5
+ @Injectable()
6
+ export class InMemoryUserRepository implements UserRepository {
7
+ async findAll(): Promise<User[]> {
8
+ return [new User('1', 'user@example.com', 'Demo User')];
9
+ }
10
+ }
@@ -0,0 +1,14 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { User } from '../../domain/entities/user.entity';
3
+ import { UserRepository } from '../../domain/repositories/user.repository';
4
+ import { PrismaService } from '../prisma/prisma.service';
5
+
6
+ @Injectable()
7
+ export class PrismaUserRepository implements UserRepository {
8
+ constructor(private readonly prisma: PrismaService) {}
9
+
10
+ async findAll(): Promise<User[]> {
11
+ const rows = await this.prisma.user.findMany();
12
+ return rows.map((r) => new User(r.id, r.email, r.name));
13
+ }
14
+ }
@@ -0,0 +1,18 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { InjectModel } from '@nestjs/sequelize';
3
+ import { User as DomainUser } from '../../domain/entities/user.entity';
4
+ import { UserRepository } from '../../domain/repositories/user.repository';
5
+ import { User } from '../sequelize/models/user.model';
6
+
7
+ @Injectable()
8
+ export class SequelizeUserRepository implements UserRepository {
9
+ constructor(
10
+ @InjectModel(User)
11
+ private readonly userModel: typeof User,
12
+ ) {}
13
+
14
+ async findAll(): Promise<DomainUser[]> {
15
+ const rows = await this.userModel.findAll();
16
+ return rows.map((r) => new DomainUser(r.id, r.email, r.name ?? ''));
17
+ }
18
+ }
@@ -0,0 +1,19 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { InjectRepository } from '@nestjs/typeorm';
3
+ import { Repository } from 'typeorm';
4
+ import { User } from '../../domain/entities/user.entity';
5
+ import { UserRepository } from '../../domain/repositories/user.repository';
6
+ import { UserEntity } from '../typeorm/entities/user.entity';
7
+
8
+ @Injectable()
9
+ export class TypeormUserRepository implements UserRepository {
10
+ constructor(
11
+ @InjectRepository(UserEntity)
12
+ private readonly repo: Repository<UserEntity>,
13
+ ) {}
14
+
15
+ async findAll(): Promise<User[]> {
16
+ const rows = await this.repo.find();
17
+ return rows.map((r) => new User(r.id, r.email, r.name ?? ''));
18
+ }
19
+ }
@@ -0,0 +1,6 @@
1
+ import { Global, Module } from '@nestjs/common';
2
+ import { PrismaService } from './prisma.service';
3
+
4
+ @Global()
5
+ @Module({ providers: [PrismaService], exports: [PrismaService] })
6
+ export class PrismaModule {}
@@ -0,0 +1,8 @@
1
+ import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
2
+ import { PrismaClient } from '@prisma/client';
3
+
4
+ @Injectable()
5
+ export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
6
+ async onModuleInit() { await this.$connect(); }
7
+ async onModuleDestroy() { await this.$disconnect(); }
8
+ }
@@ -0,0 +1,21 @@
1
+ {{#if useReflectMetadata}}import 'reflect-metadata';
2
+ {{/if}}import { NestFactory } from '@nestjs/core';
3
+ import { AppModule } from './app.module';
4
+ {{#if swagger}}
5
+ import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
6
+ {{/if}}
7
+
8
+ async function bootstrap() {
9
+ const app = await NestFactory.create(AppModule);
10
+ app.setGlobalPrefix('api');
11
+ {{#if swagger}}
12
+ const config = new DocumentBuilder()
13
+ .setTitle('{{projectSlug}}')
14
+ .setDescription('{{description}}')
15
+ .setVersion('1.0')
16
+ .build();
17
+ SwaggerModule.setup('docs', app, SwaggerModule.createDocument(app, config));
18
+ {{/if}}
19
+ await app.listen(process.env.PORT ?? 3000);
20
+ }
21
+ bootstrap();
@@ -0,0 +1,9 @@
1
+ export class AppError extends Error {
2
+ constructor(
3
+ message: string,
4
+ public readonly statusCode = 400,
5
+ ) {
6
+ super(message);
7
+ this.name = 'AppError';
8
+ }
9
+ }
@@ -0,0 +1,17 @@
1
+ import { Test } from '@nestjs/testing';
2
+ import { HealthController } from '../src/infrastructure/http/health.controller';
3
+
4
+ describe('HealthController', () => {
5
+ it('should return ok status', async () => {
6
+ const module = await Test.createTestingModule({
7
+ controllers: [HealthController],
8
+ }).compile();
9
+
10
+ const controller = module.get(HealthController);
11
+ const result = controller.check();
12
+
13
+ expect(result.status).toBe('ok');
14
+ expect(result.service).toBe('{{projectSlug}}');
15
+ expect(result.architecture).toBe('clean');
16
+ });
17
+ });
@@ -0,0 +1,46 @@
1
+ import 'dotenv/config';
2
+ import express from 'express';
3
+ import cors from 'cors';
4
+ import helmet from 'helmet';
5
+ import { healthRouter } from './modules/health/health.routes.js';
6
+ import { usersRouter } from './modules/users/users.routes.js';
7
+ {{#if useTypeorm}}
8
+ import { initTypeorm } from './infra/typeorm/data-source.js';
9
+ {{/if}}
10
+ {{#if useSequelize}}
11
+ import { initSequelize } from './infra/sequelize/sequelize.js';
12
+ {{/if}}
13
+ {{#if swagger}}
14
+ import { setupSwagger } from './infra/swagger/setup.js';
15
+ {{/if}}
16
+ {{#if useClerk}}
17
+ import { clerkAuth } from './infra/auth/clerk.middleware.js';
18
+ {{/if}}
19
+
20
+ async function bootstrap() {
21
+ {{#if useTypeorm}}
22
+ await initTypeorm();
23
+ {{/if}}
24
+ {{#if useSequelize}}
25
+ await initSequelize();
26
+ {{/if}}
27
+
28
+ const app = express();
29
+ app.use(helmet());
30
+ app.use(cors());
31
+ app.use(express.json());
32
+ {{#if useClerk}}
33
+ app.use(clerkAuth);
34
+ {{/if}}
35
+ {{#if swagger}}
36
+ setupSwagger(app);
37
+ {{/if}}
38
+
39
+ app.use('/api/health', healthRouter);
40
+ app.use('/api/users', usersRouter);
41
+
42
+ const port = process.env.PORT ?? 3000;
43
+ app.listen(port, () => console.log(`🚀 {{projectSlug}} (modular) on :${port}`));
44
+ }
45
+
46
+ bootstrap();
@@ -0,0 +1,3 @@
1
+ export const databaseConfig = {
2
+ url: process.env.DATABASE_URL ?? '',
3
+ };
@@ -0,0 +1,7 @@
1
+ import { Router } from 'express';
2
+
3
+ export const healthRouter = Router();
4
+
5
+ healthRouter.get('/', (_req, res) => {
6
+ res.json({ status: 'ok', service: '{{projectSlug}}', architecture: 'modular-monolith' });
7
+ });
@@ -0,0 +1,55 @@
1
+ import { Router } from 'express';
2
+ {{#if usePrisma}}
3
+ import { prisma } from '../../infra/prisma/client.js';
4
+ {{/if}}
5
+ {{#if useTypeorm}}
6
+ import { AppDataSource } from '../../infra/typeorm/data-source.js';
7
+ import { UserEntity } from '../../infra/typeorm/entities/user.entity.js';
8
+ {{/if}}
9
+ {{#if useDrizzle}}
10
+ import { db } from '../../infra/drizzle/client.js';
11
+ import { users } from '../../infra/drizzle/schema.js';
12
+ {{/if}}
13
+ {{#if useSequelize}}
14
+ import { User } from '../../infra/sequelize/models/user.model.js';
15
+ {{/if}}
16
+ {{#if useJwt}}
17
+ import { jwtMiddleware } from '../../infra/auth/jwt.middleware.js';
18
+ {{/if}}
19
+ {{#if useClerk}}
20
+ import { requireClerkAuth } from '../../infra/auth/clerk.middleware.js';
21
+ {{/if}}
22
+
23
+ export const usersRouter = Router();
24
+
25
+ const listUsers = async (_req: import('express').Request, res: import('express').Response) => {
26
+ {{#if usePrisma}}
27
+ const rows = await prisma.user.findMany();
28
+ res.json(rows);
29
+ {{/if}}
30
+ {{#if useTypeorm}}
31
+ const rows = await AppDataSource.getRepository(UserEntity).find();
32
+ res.json(rows);
33
+ {{/if}}
34
+ {{#if useDrizzle}}
35
+ const rows = await db.select().from(users);
36
+ res.json(rows);
37
+ {{/if}}
38
+ {{#if useSequelize}}
39
+ const rows = await User.findAll();
40
+ res.json(rows);
41
+ {{/if}}
42
+ {{#unless hasRealOrm}}
43
+ res.json([{ id: '1', email: 'user@example.com', name: 'Demo User' }]);
44
+ {{/unless}}
45
+ };
46
+
47
+ {{#if useJwt}}
48
+ usersRouter.get('/', jwtMiddleware, listUsers);
49
+ {{else}}
50
+ {{#if useClerk}}
51
+ usersRouter.get('/', requireClerkAuth, listUsers);
52
+ {{else}}
53
+ usersRouter.get('/', listUsers);
54
+ {{/if}}
55
+ {{/if}}
@@ -0,0 +1 @@
1
+ export const APP_NAME = '{{projectSlug}}';
@@ -0,0 +1,33 @@
1
+ import 'dotenv/config';
2
+ import Fastify from 'fastify';
3
+ import cors from '@fastify/cors';
4
+ import helmet from '@fastify/helmet';
5
+ import { healthRoutes } from './modules/health/health.routes.js';
6
+ import { usersRoutes } from './modules/users/users.routes.js';
7
+ {{#if useTypeorm}}
8
+ import { initTypeorm } from './infra/typeorm/data-source.js';
9
+ {{/if}}
10
+ {{#if useSequelize}}
11
+ import { initSequelize } from './infra/sequelize/sequelize.js';
12
+ {{/if}}
13
+ {{#if swagger}}
14
+ import { setupSwagger } from './infra/swagger/setup.js';
15
+ {{/if}}
16
+
17
+ {{#if useTypeorm}}
18
+ await initTypeorm();
19
+ {{/if}}
20
+ {{#if useSequelize}}
21
+ await initSequelize();
22
+ {{/if}}
23
+
24
+ const app = Fastify({ logger: true });
25
+ await app.register(cors);
26
+ await app.register(helmet);
27
+ {{#if swagger}}
28
+ await setupSwagger(app);
29
+ {{/if}}
30
+ await app.register(healthRoutes);
31
+ await app.register(usersRoutes);
32
+
33
+ await app.listen({ port: Number(process.env.PORT ?? 3000), host: '0.0.0.0' });
@@ -0,0 +1,3 @@
1
+ export const databaseConfig = {
2
+ url: process.env.DATABASE_URL ?? '',
3
+ };