@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,12 @@
1
+ import { type ProjectConfig } from '@node-initializr/shared';
2
+ import { type GeneratedFile } from './template-engine.js';
3
+ export interface GenerateResult {
4
+ files: GeneratedFile[];
5
+ buffer: Buffer;
6
+ fileName: string;
7
+ filesGenerated: number;
8
+ }
9
+ export declare function buildProjectConfig(partial: Partial<ProjectConfig> & Pick<ProjectConfig, 'name'>): ProjectConfig;
10
+ export declare function renderProject(config: ProjectConfig): GeneratedFile[];
11
+ export declare function generateProject(config: ProjectConfig): Promise<GenerateResult>;
12
+ export declare function writeProject(files: GeneratedFile[], targetDir: string): Promise<void>;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildProjectConfig = buildProjectConfig;
37
+ exports.renderProject = renderProject;
38
+ exports.generateProject = generateProject;
39
+ exports.writeProject = writeProject;
40
+ const shared_1 = require("@node-initializr/shared");
41
+ const fs = __importStar(require("fs"));
42
+ const path = __importStar(require("path"));
43
+ const template_engine_js_1 = require("./template-engine.js");
44
+ const validate_js_1 = require("./validate.js");
45
+ const zip_js_1 = require("./zip.js");
46
+ const engine = new template_engine_js_1.TemplateEngine();
47
+ function buildProjectConfig(partial) {
48
+ return {
49
+ ...shared_1.DEFAULT_PROJECT_CONFIG,
50
+ description: '',
51
+ ...partial,
52
+ };
53
+ }
54
+ function renderProject(config) {
55
+ const errors = (0, validate_js_1.validateProjectConfig)(config);
56
+ if (errors.length > 0) {
57
+ throw new Error(errors.join('; '));
58
+ }
59
+ return engine.renderProject(config);
60
+ }
61
+ async function generateProject(config) {
62
+ const files = renderProject(config);
63
+ const buffer = await (0, zip_js_1.createZip)(files);
64
+ return {
65
+ files,
66
+ buffer,
67
+ fileName: `${config.name}.zip`,
68
+ filesGenerated: files.length,
69
+ };
70
+ }
71
+ async function writeProject(files, targetDir) {
72
+ for (const file of files) {
73
+ const filePath = path.join(targetDir, file.path);
74
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
75
+ fs.writeFileSync(filePath, file.content, 'utf-8');
76
+ }
77
+ }
@@ -0,0 +1,4 @@
1
+ export { TemplateEngine, type GeneratedFile } from './template-engine.js';
2
+ export { createZip } from './zip.js';
3
+ export { validateProjectConfig } from './validate.js';
4
+ export { buildProjectConfig, generateProject, renderProject, writeProject, type GenerateResult, } from './generate.js';
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.writeProject = exports.renderProject = exports.generateProject = exports.buildProjectConfig = exports.validateProjectConfig = exports.createZip = exports.TemplateEngine = void 0;
4
+ var template_engine_js_1 = require("./template-engine.js");
5
+ Object.defineProperty(exports, "TemplateEngine", { enumerable: true, get: function () { return template_engine_js_1.TemplateEngine; } });
6
+ var zip_js_1 = require("./zip.js");
7
+ Object.defineProperty(exports, "createZip", { enumerable: true, get: function () { return zip_js_1.createZip; } });
8
+ var validate_js_1 = require("./validate.js");
9
+ Object.defineProperty(exports, "validateProjectConfig", { enumerable: true, get: function () { return validate_js_1.validateProjectConfig; } });
10
+ var generate_js_1 = require("./generate.js");
11
+ Object.defineProperty(exports, "buildProjectConfig", { enumerable: true, get: function () { return generate_js_1.buildProjectConfig; } });
12
+ Object.defineProperty(exports, "generateProject", { enumerable: true, get: function () { return generate_js_1.generateProject; } });
13
+ Object.defineProperty(exports, "renderProject", { enumerable: true, get: function () { return generate_js_1.renderProject; } });
14
+ Object.defineProperty(exports, "writeProject", { enumerable: true, get: function () { return generate_js_1.writeProject; } });
@@ -0,0 +1,24 @@
1
+ import type { ProjectConfig } from '@node-initializr/shared';
2
+ export interface GeneratedFile {
3
+ path: string;
4
+ content: string;
5
+ }
6
+ export declare class TemplateEngine {
7
+ private readonly templatesDir;
8
+ constructor(templatesDir?: string);
9
+ renderProject(config: ProjectConfig): GeneratedFile[];
10
+ private resolveTemplatesRoot;
11
+ private resolveTemplateDirs;
12
+ private resolveArchDir;
13
+ private buildContext;
14
+ private getDbDriver;
15
+ private getTypeormDriver;
16
+ private getSequelizeDialect;
17
+ private getDrizzleDriver;
18
+ private getPmRunDev;
19
+ private getOrmPackage;
20
+ private walkAndRender;
21
+ private shouldSkipDir;
22
+ private shouldIncludeFile;
23
+ private resolveOutputPath;
24
+ }
@@ -0,0 +1,472 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.TemplateEngine = void 0;
40
+ const fs = __importStar(require("fs"));
41
+ const handlebars_1 = __importDefault(require("handlebars"));
42
+ const path = __importStar(require("path"));
43
+ class TemplateEngine {
44
+ templatesDir;
45
+ constructor(templatesDir) {
46
+ handlebars_1.default.registerHelper('eq', (a, b) => a === b);
47
+ this.templatesDir = templatesDir ?? this.resolveTemplatesRoot();
48
+ }
49
+ renderProject(config) {
50
+ const context = this.buildContext(config);
51
+ const templateDirs = this.resolveTemplateDirs(config);
52
+ const fileMap = new Map();
53
+ for (const dir of templateDirs) {
54
+ if (!fs.existsSync(dir)) {
55
+ throw new Error(`Template set not found: ${dir}`);
56
+ }
57
+ for (const file of this.walkAndRender(dir, '', context)) {
58
+ fileMap.set(file.path, file);
59
+ }
60
+ }
61
+ if (fileMap.size === 0) {
62
+ throw new Error('Nenhum arquivo gerado — verifique framework e arquitetura');
63
+ }
64
+ return Array.from(fileMap.values());
65
+ }
66
+ resolveTemplatesRoot() {
67
+ const candidates = [
68
+ path.join(__dirname, 'templates'),
69
+ path.join(__dirname, '..', 'templates'),
70
+ path.join(process.cwd(), 'packages', 'generator', 'dist', 'templates'),
71
+ path.join(process.cwd(), 'packages', 'generator', 'templates'),
72
+ ];
73
+ for (const candidate of candidates) {
74
+ if (fs.existsSync(candidate)) {
75
+ return candidate;
76
+ }
77
+ }
78
+ throw new Error(`Templates não encontrados. Procurou em: ${candidates.join(', ')}`);
79
+ }
80
+ resolveTemplateDirs(config) {
81
+ const arch = this.resolveArchDir(config.architecture);
82
+ const sharedDir = path.join(this.templatesDir, `shared-${config.framework}`);
83
+ const dirs = [
84
+ path.join(this.templatesDir, `base-${config.framework}`),
85
+ path.join(this.templatesDir, arch, config.framework),
86
+ ];
87
+ if (fs.existsSync(sharedDir)) {
88
+ dirs.splice(1, 0, sharedDir);
89
+ }
90
+ return dirs;
91
+ }
92
+ resolveArchDir(architecture) {
93
+ const map = {
94
+ clean: 'arch-clean',
95
+ mvc: 'arch-mvc',
96
+ 'modular-monolith': 'arch-modular',
97
+ };
98
+ return map[architecture];
99
+ }
100
+ buildContext(config) {
101
+ const ext = config.language === 'typescript' ? 'ts' : 'js';
102
+ return {
103
+ ...config,
104
+ ext,
105
+ projectSlug: config.name,
106
+ npmName: config.name.replace(/-/g, '_'),
107
+ year: new Date().getFullYear(),
108
+ hasDatabase: config.database !== 'none',
109
+ hasOrm: config.orm !== 'none',
110
+ hasAuth: config.auth !== 'none',
111
+ hasRedis: config.redis,
112
+ needsRedis: config.redis || config.messageBroker === 'bullmq',
113
+ hasMessageBroker: config.messageBroker !== 'none',
114
+ isTypescript: config.language === 'typescript',
115
+ usePrisma: config.orm === 'prisma' && config.database !== 'none',
116
+ useTypeorm: config.orm === 'typeorm' && config.database !== 'none',
117
+ useDrizzle: config.orm === 'drizzle' &&
118
+ (config.database === 'postgresql' || config.database === 'mysql'),
119
+ useSequelize: config.orm === 'sequelize' &&
120
+ (config.database === 'postgresql' || config.database === 'mysql'),
121
+ useReflectMetadata: config.orm === 'typeorm' || config.orm === 'sequelize',
122
+ useJwt: config.auth === 'jwt',
123
+ useClerk: config.auth === 'clerk',
124
+ useBullmq: config.messageBroker === 'bullmq',
125
+ useRabbitmq: config.messageBroker === 'rabbitmq',
126
+ usePostgres: config.database === 'postgresql',
127
+ useMysql: config.database === 'mysql',
128
+ useMongodb: config.database === 'mongodb',
129
+ isCleanArch: config.architecture === 'clean',
130
+ isMvc: config.architecture === 'mvc',
131
+ isModular: config.architecture === 'modular-monolith',
132
+ hasRealOrm: config.orm === 'prisma' ||
133
+ config.orm === 'typeorm' ||
134
+ config.orm === 'drizzle' ||
135
+ config.orm === 'sequelize',
136
+ dbDriver: this.getDbDriver(config),
137
+ typeormDriver: this.getTypeormDriver(config),
138
+ sequelizeDialect: this.getSequelizeDialect(config),
139
+ drizzleDriver: this.getDrizzleDriver(config),
140
+ ormPackage: this.getOrmPackage(config),
141
+ isPnpm: config.packageManager === 'pnpm',
142
+ isYarn: config.packageManager === 'yarn',
143
+ isNpm: config.packageManager === 'npm',
144
+ pmInstall: config.packageManager === 'pnpm'
145
+ ? 'pnpm install'
146
+ : config.packageManager === 'yarn'
147
+ ? 'yarn install --frozen-lockfile'
148
+ : 'npm ci',
149
+ pmRunBuild: config.packageManager === 'pnpm'
150
+ ? 'pnpm run build'
151
+ : config.packageManager === 'yarn'
152
+ ? 'yarn build'
153
+ : 'npm run build',
154
+ pmRunTest: config.packageManager === 'pnpm'
155
+ ? 'pnpm test'
156
+ : config.packageManager === 'yarn'
157
+ ? 'yarn test'
158
+ : 'npm test',
159
+ pmRunDev: this.getPmRunDev(config),
160
+ pmInstallDev: config.packageManager === 'pnpm'
161
+ ? 'pnpm install'
162
+ : config.packageManager === 'yarn'
163
+ ? 'yarn install'
164
+ : 'npm install',
165
+ };
166
+ }
167
+ getDbDriver(config) {
168
+ const map = {
169
+ postgresql: 'pg',
170
+ mysql: 'mysql2',
171
+ mongodb: 'mongodb',
172
+ };
173
+ return map[config.database] ?? 'pg';
174
+ }
175
+ getTypeormDriver(config) {
176
+ const map = {
177
+ postgresql: 'postgres',
178
+ mysql: 'mysql',
179
+ mongodb: 'mongodb',
180
+ };
181
+ return map[config.database] ?? 'postgres';
182
+ }
183
+ getSequelizeDialect(config) {
184
+ const map = {
185
+ postgresql: 'postgres',
186
+ mysql: 'mysql',
187
+ };
188
+ return map[config.database] ?? 'postgres';
189
+ }
190
+ getDrizzleDriver(config) {
191
+ if (config.database === 'mysql')
192
+ return 'mysql2';
193
+ if (config.database === 'mongodb')
194
+ return 'mongodb';
195
+ return 'pg';
196
+ }
197
+ getPmRunDev(config) {
198
+ const script = config.framework === 'nestjs' ? 'start:dev' : 'dev';
199
+ if (config.packageManager === 'pnpm')
200
+ return `pnpm run ${script}`;
201
+ if (config.packageManager === 'yarn')
202
+ return `yarn ${script}`;
203
+ return `npm run ${script}`;
204
+ }
205
+ getOrmPackage(config) {
206
+ const map = {
207
+ prisma: '@prisma/client',
208
+ typeorm: 'typeorm',
209
+ drizzle: 'drizzle-orm',
210
+ sequelize: 'sequelize',
211
+ };
212
+ return map[config.orm] ?? '';
213
+ }
214
+ walkAndRender(dir, relativePath, context) {
215
+ if (!fs.existsSync(dir))
216
+ return [];
217
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
218
+ const files = [];
219
+ for (const entry of entries) {
220
+ const entryRelative = path.join(relativePath, entry.name);
221
+ if (entry.isDirectory()) {
222
+ if (this.shouldSkipDir(entry.name, context, relativePath))
223
+ continue;
224
+ files.push(...this.walkAndRender(path.join(dir, entry.name), entryRelative, context));
225
+ continue;
226
+ }
227
+ if (!entry.name.endsWith('.hbs'))
228
+ continue;
229
+ if (!this.shouldIncludeFile(entryRelative, context))
230
+ continue;
231
+ const raw = fs.readFileSync(path.join(dir, entry.name), 'utf-8');
232
+ const template = handlebars_1.default.compile(raw, { noEscape: true });
233
+ files.push({
234
+ path: this.resolveOutputPath(entryRelative, context),
235
+ content: template(context),
236
+ });
237
+ }
238
+ return files;
239
+ }
240
+ shouldSkipDir(dirName, ctx, parentPath) {
241
+ const conditionalDirs = {
242
+ docker: 'docker',
243
+ 'github-actions': 'githubActions',
244
+ prisma: 'usePrisma',
245
+ typeorm: 'useTypeorm',
246
+ drizzle: 'useDrizzle',
247
+ sequelize: 'useSequelize',
248
+ auth: 'hasAuth',
249
+ swagger: 'swagger',
250
+ tests: 'jest',
251
+ };
252
+ if (parentPath.includes('auth') && dirName === 'jwt' && !ctx.useJwt)
253
+ return true;
254
+ if (parentPath.includes('auth') && dirName === 'clerk' && !ctx.useClerk)
255
+ return true;
256
+ if (parentPath.includes('infra') && dirName === 'prisma' && !ctx.usePrisma)
257
+ return true;
258
+ if (parentPath.includes('infra') &&
259
+ dirName === 'typeorm' &&
260
+ !ctx.useTypeorm)
261
+ return true;
262
+ if (parentPath.includes('infra') &&
263
+ dirName === 'drizzle' &&
264
+ !ctx.useDrizzle)
265
+ return true;
266
+ if (parentPath.includes('infra') &&
267
+ dirName === 'sequelize' &&
268
+ !ctx.useSequelize)
269
+ return true;
270
+ if (parentPath.includes('infrastructure') &&
271
+ dirName === 'prisma' &&
272
+ !ctx.usePrisma) {
273
+ return true;
274
+ }
275
+ if (parentPath.includes('infrastructure') &&
276
+ dirName === 'typeorm' &&
277
+ !ctx.useTypeorm) {
278
+ return true;
279
+ }
280
+ if (parentPath.includes('infrastructure') &&
281
+ dirName === 'drizzle' &&
282
+ !ctx.useDrizzle) {
283
+ return true;
284
+ }
285
+ if (parentPath.includes('infrastructure') &&
286
+ dirName === 'sequelize' &&
287
+ !ctx.useSequelize) {
288
+ return true;
289
+ }
290
+ const normParent = parentPath.replace(/\\/g, '/');
291
+ if (normParent === 'src/infra' &&
292
+ (dirName === 'typeorm' ||
293
+ dirName === 'drizzle' ||
294
+ dirName === 'sequelize') &&
295
+ ctx.isCleanArch) {
296
+ return true;
297
+ }
298
+ if (normParent === 'src/infrastructure' &&
299
+ (dirName === 'typeorm' ||
300
+ dirName === 'drizzle' ||
301
+ dirName === 'sequelize') &&
302
+ !ctx.isCleanArch) {
303
+ return true;
304
+ }
305
+ const flag = conditionalDirs[dirName];
306
+ return flag ? !ctx[flag] : false;
307
+ }
308
+ shouldIncludeFile(filePath, ctx) {
309
+ const norm = filePath.replace(/\\/g, '/');
310
+ if (norm.includes('/prisma/') && !ctx.usePrisma)
311
+ return false;
312
+ if (norm.includes('/typeorm/') && !ctx.useTypeorm)
313
+ return false;
314
+ if (norm.includes('/drizzle/') && !ctx.useDrizzle)
315
+ return false;
316
+ if (norm.includes('/sequelize/') && !ctx.useSequelize)
317
+ return false;
318
+ if (norm.includes('prisma-user.repository') && !ctx.usePrisma)
319
+ return false;
320
+ if (norm.includes('typeorm-user.repository') && !ctx.useTypeorm)
321
+ return false;
322
+ if (norm.includes('drizzle-user.repository') && !ctx.useDrizzle)
323
+ return false;
324
+ if (norm.includes('sequelize-user.repository') && !ctx.useSequelize)
325
+ return false;
326
+ if (norm.includes('in-memory-user.repository') && ctx.hasRealOrm)
327
+ return false;
328
+ if (norm.includes('infra/prisma') && !ctx.usePrisma)
329
+ return false;
330
+ if (norm.includes('infra/typeorm') && !ctx.useTypeorm)
331
+ return false;
332
+ if (norm.includes('infra/drizzle') && !ctx.useDrizzle)
333
+ return false;
334
+ if (norm.includes('infra/sequelize') && !ctx.useSequelize)
335
+ return false;
336
+ if (norm.includes('auth/jwt') && !ctx.useJwt)
337
+ return false;
338
+ if (norm.includes('auth/clerk') && !ctx.useClerk)
339
+ return false;
340
+ if (norm.includes('infra/swagger') && !ctx.swagger)
341
+ return false;
342
+ if (norm.includes('jwt.middleware') && !ctx.useJwt)
343
+ return false;
344
+ if (norm.includes('jwt-auth.guard') && !ctx.useJwt)
345
+ return false;
346
+ if (norm.includes('jwt.guard') && !ctx.useJwt)
347
+ return false;
348
+ if (norm.includes('jwt.strategy') && !ctx.useJwt)
349
+ return false;
350
+ if (norm.includes('jwt.module') && !ctx.useJwt)
351
+ return false;
352
+ if (norm.includes('clerk-auth.guard') && !ctx.useClerk)
353
+ return false;
354
+ if (norm.includes('clerk.guard') && !ctx.useClerk)
355
+ return false;
356
+ if (norm.includes('clerk.middleware') && !ctx.useClerk)
357
+ return false;
358
+ if (norm.includes('tsconfig.json') && !ctx.isTypescript)
359
+ return false;
360
+ if (norm.includes('nest-cli.json') && !ctx.isTypescript)
361
+ return false;
362
+ if (norm.includes('drizzle.config') && !ctx.useDrizzle)
363
+ return false;
364
+ if (norm.includes('.js.hbs') && ctx.isTypescript)
365
+ return false;
366
+ return true;
367
+ }
368
+ resolveOutputPath(relativePath, ctx) {
369
+ let output = relativePath.replace(/\.hbs$/, '').replace(/\\/g, '/');
370
+ const pathMappings = {
371
+ 'docker/Dockerfile': 'Dockerfile',
372
+ 'docker/docker-compose.yml': 'docker-compose.yml',
373
+ 'github-actions/ci.yml': '.github/workflows/ci.yml',
374
+ 'tests/health.spec.ts': 'test/health.spec.ts',
375
+ 'tests/health.test.ts': 'test/health.test.ts',
376
+ 'tests/health.test': 'test/health.test.ts',
377
+ 'drizzle/drizzle.config.ts': 'drizzle.config.ts',
378
+ 'drizzle/drizzle.config': 'drizzle.config.ts',
379
+ };
380
+ for (const [from, to] of Object.entries(pathMappings)) {
381
+ if (output === from || output.endsWith(`/${from}`)) {
382
+ output = to;
383
+ break;
384
+ }
385
+ }
386
+ const sourceExt = ctx.ext;
387
+ const extensionlessSources = [
388
+ 'src/index',
389
+ 'src/main',
390
+ 'src/app.module',
391
+ 'src/infrastructure/http/health.routes',
392
+ 'src/infrastructure/http/users.routes',
393
+ 'src/infrastructure/http/health.controller',
394
+ 'src/infrastructure/http/users.controller',
395
+ 'src/controllers/health.controller',
396
+ 'src/controllers/users.controller',
397
+ 'src/services/users.service',
398
+ 'src/models/user.model',
399
+ 'src/domain/entities/user.entity',
400
+ 'src/domain/repositories/user.repository',
401
+ 'src/application/use-cases/get-users.use-case',
402
+ 'src/infrastructure/persistence/prisma-user.repository',
403
+ 'src/infrastructure/persistence/typeorm-user.repository',
404
+ 'src/infrastructure/persistence/drizzle-user.repository',
405
+ 'src/infrastructure/persistence/sequelize-user.repository',
406
+ 'src/infrastructure/persistence/in-memory-user.repository',
407
+ 'src/infrastructure/prisma/prisma.module',
408
+ 'src/infrastructure/prisma/prisma.service',
409
+ 'src/infrastructure/typeorm/typeorm.module',
410
+ 'src/infrastructure/typeorm/entities/user.entity',
411
+ 'src/infrastructure/drizzle/drizzle.module',
412
+ 'src/infrastructure/drizzle/drizzle.service',
413
+ 'src/infrastructure/drizzle/schema',
414
+ 'src/infrastructure/sequelize/sequelize.module',
415
+ 'src/infrastructure/sequelize/models/user.model',
416
+ 'src/infra/prisma/prisma.module',
417
+ 'src/infra/prisma/prisma.service',
418
+ 'src/infra/prisma/client',
419
+ 'src/infra/typeorm/data-source',
420
+ 'src/infra/typeorm/entities/user.entity',
421
+ 'src/infra/drizzle/client',
422
+ 'src/infra/drizzle/schema',
423
+ 'src/infra/sequelize/sequelize',
424
+ 'src/infra/sequelize/models/user.model',
425
+ 'src/infra/database/users.repository',
426
+ 'src/infra/auth/jwt.middleware',
427
+ 'src/infra/auth/clerk.middleware',
428
+ 'src/infra/auth/jwt/jwt-auth.guard',
429
+ 'src/infra/auth/jwt/jwt.strategy',
430
+ 'src/infra/auth/jwt/jwt.module',
431
+ 'src/infra/auth/clerk/clerk-auth.guard',
432
+ 'src/infrastructure/typeorm/typeorm.module',
433
+ 'src/infrastructure/typeorm/entities/user.entity',
434
+ 'src/infrastructure/drizzle/drizzle.module',
435
+ 'src/infrastructure/drizzle/drizzle.service',
436
+ 'src/infrastructure/drizzle/schema',
437
+ 'src/infra/typeorm/typeorm.module',
438
+ 'src/infra/typeorm/entities/user.entity',
439
+ 'src/infra/drizzle/drizzle.module',
440
+ 'src/infra/drizzle/drizzle.service',
441
+ 'src/infra/drizzle/schema',
442
+ 'src/infra/swagger/setup',
443
+ 'src/modules/health/health.module',
444
+ 'src/modules/health/health.controller',
445
+ 'src/modules/users/users.module',
446
+ 'src/modules/users/users.controller',
447
+ 'src/modules/users/users.service',
448
+ 'src/config/config.module',
449
+ 'src/shared/errors/app.error',
450
+ 'src/shared/constants',
451
+ 'src/config/env',
452
+ 'src/modules/health/health.routes',
453
+ 'src/modules/users/users.routes',
454
+ 'src/infra/database',
455
+ 'test/health.test',
456
+ ];
457
+ for (const source of extensionlessSources) {
458
+ if (output === source || output.endsWith(`/${source}`)) {
459
+ output = `${output}.${sourceExt}`;
460
+ break;
461
+ }
462
+ }
463
+ if (ctx.isTypescript) {
464
+ output = output.replace(/\.js$/, '.ts');
465
+ }
466
+ else {
467
+ output = output.replace(/\.ts$/, '.js');
468
+ }
469
+ return output.replace(/\\/g, '/');
470
+ }
471
+ }
472
+ exports.TemplateEngine = TemplateEngine;
@@ -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,4 @@
1
+ export const env = {
2
+ port: Number(process.env.PORT ?? 3000),
3
+ nodeEnv: process.env.NODE_ENV ?? 'development',
4
+ };
@@ -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
+ }