ddd-backend-cli 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ <h1 align="left">Backend CLI Automation</h1>
2
+ <img src="https://i.ibb.co/0VfX0r3F/backend-Automation.png" alt="backend Automation" border="0">
3
+
4
+ ###
5
+
6
+ <p align="left">CLI para generar automáticamente la estructura base de un módulo CRUD en un proyecto Backend usando Node.js + TypeScript + Express + EJS templates.<br><br>Este proyecto te permite crear tu propio template de Backend y personalizarlo usando solo comandos, sin necesidad de escribir todo el código repetitivo cada vez.</p>
7
+
8
+ Documentación paso a paso en mi Notion, para que puedas replicar la lógica y adaptarlo a tu manera: https://www.notion.so/oscarmolina/Automatizacion-Backend-3037c9c9fb1780f5bb06db3a9fb9ef83?source=copy_link
9
+
10
+ ###
11
+
12
+ <h2 align="left">Repositorio del CLI</h2>
13
+
14
+ ###
15
+
16
+ ```bash
17
+ #clonar el proyecto
18
+ git clone https://github.com/oscarMolina1523/BackendAutomation
19
+
20
+ #navegar dentro de la carpeta
21
+ cd backend-cli
22
+
23
+ #instalar dependencias
24
+ npm install
25
+
26
+ #hacer build del proyecto
27
+ npm run build
28
+
29
+ #crear link de direccion en la pc
30
+ npm link
31
+ ```
32
+ ###
33
+
34
+ <h2 align="left">Estructura del Proyecto CLI</h2>
35
+
36
+ ###
37
+
38
+ ```bash
39
+ backend-cli/
40
+
41
+ ├── src/
42
+ │ ├── index.ts <-----ejcuta todos los procesos
43
+ │ ├── initializer/
44
+ │ │ ├── createBaseStructure.ts
45
+ │ │ ├── createGitIgnore.ts
46
+ │ │ ├── createPackageJson.ts
47
+ │ │ ├── createTsConfig.ts
48
+ │ │ ├── initProject.ts <---ejecuta el flujo
49
+ │ │ └── installDependencies.ts
50
+ │ ├── generators/
51
+ │ │ ├──modules/
52
+ │ │ ├── baseModel.ts
53
+ │ │ ├── containerRegistry.ts
54
+ │ │ ├── createOpenApiBase.ts
55
+ │ │ ├── fileCreator.ts
56
+ │ │ ├── generateModule.ts <---ejecuta el flujo de trabajo
57
+ │ │ ├── routeRegistry.ts
58
+ │ │ ├── structure.ts
59
+ │ │ ├── types.ts
60
+ │ │ └── openApiRegistry.ts
61
+ ├── templates/
62
+ │ ├── controller.ejs
63
+ │ ├── dto.ejs
64
+ │ ├── entity.ejs
65
+ │ ├── path.ejs
66
+ │ ├── service.interface.ejs
67
+ │ ├── service.impl.ejs
68
+ │ ├── repository.interface.ejs
69
+ │ ├── repository.impl.ejs
70
+ │ ├── routes.ejs
71
+ │ └── schema.ejs
72
+
73
+ ├── dist/ ← Se genera automáticamente con npm run build
74
+ ├── package.json
75
+ ├── tsconfig.json
76
+ ```
77
+ ###
78
+
79
+ <h2 align="left">¿Cómo funciona el CLI?</h2>
80
+
81
+ Este CLI utiliza:
82
+ Commander → Para manejar comandos en consola,
83
+ EJS → Para generar archivos dinámicamente usando templates,
84
+ fs-extra → Para manipulación de archivos,
85
+ TypeScript → Para tipado y compilación.
86
+
87
+ Para usarlo , debes haber ejecutado los comandos mencionados anteriormente y estar seguros
88
+ de que esta funcionando el CLI (no es necesario qeu el proyecto CLI este corriendo, con haber ejecutado sus comandos es suficiente),
89
+ debes ubicarte en el espacio sobre el que trabajaras, en mi caso el Escritorio(Desktop) y ejecutar los comandos a continuación.
90
+
91
+
92
+ ```bash
93
+
94
+ #para iniciar el proyecto nuevo y crear una base usa el siguiente comando
95
+
96
+ mycli init test-api
97
+
98
+ #donde init es el comando de inicializacion y test-api el nombre del proyecto,
99
+ # una vez creado debemos entrar en el proyecto con el comando:
100
+
101
+ cd test-api
102
+
103
+ #luego ejecutaremos el siguiente comando que se encargara de crearnos la estructura
104
+ # de carpetas y archivos de manera automatizada
105
+
106
+ mycli generate Product name:string price:number
107
+
108
+ #El CLI:
109
+ #Crea una carpeta src/product
110
+ #Genera automáticamente:
111
+ #Controller
112
+ #Service (interface + implementación)
113
+ #Repository (interface + implementación)
114
+ #Routes
115
+ #Swagger schema
116
+ #Inserta dinámicamente los campos en el template de Swagger
117
+ ```
118
+ ###
119
+ <h2 align="left">¿Donde ver la documentaciónde los endpoints?</h2>
120
+
121
+ ```bash
122
+ #en tu navegador de preferencia luego de asegurarte de que tu backend este corriendo
123
+ #debes escribir la siguiente ruta
124
+
125
+ http:localhost:3000
126
+
127
+ #tambien podrás ver la documentación y probar cada endpoint
128
+ #desde Scalar en la web usando la siguiente ruta
129
+
130
+ http:localhost:3000/api-docs
131
+
132
+ ```
133
+
134
+ <h2 align="left">✨ Autor</h2>
135
+
136
+ ###
137
+
138
+ <p align="left">Desarrollador Oscar Molina<br>💼 Desarrollador Web<br>GitHub: @oscarMolina1523<br>linkedin: https://www.linkedin.com/in/oscar-molina-916195309</p>
139
+
140
+ ###
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ensureBaseModel = ensureBaseModel;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ //this create the base model file if it does not exist to be extended by other models
10
+ async function ensureBaseModel(domainPath) {
11
+ const baseModelPath = path_1.default.join(domainPath, "entities", "base.model.ts");
12
+ if (await fs_extra_1.default.pathExists(baseModelPath)) {
13
+ return;
14
+ }
15
+ const content = `
16
+ export default abstract class BaseModel {
17
+ id: string;
18
+
19
+ constructor(id: string) {
20
+ this.id = id;
21
+ }
22
+ }
23
+ `;
24
+ await fs_extra_1.default.writeFile(baseModelPath, content.trim());
25
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerModuleInContainer = registerModuleInContainer;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ //this register every module's dependencies in the dependency container
10
+ async function registerModuleInContainer(webApiPath, name, moduleName) {
11
+ const registryPath = path_1.default.join(webApiPath, "container", "dependencyContainer.ts");
12
+ await fs_extra_1.default.ensureDir(path_1.default.dirname(registryPath));
13
+ if (!(await fs_extra_1.default.pathExists(registryPath))) {
14
+ await fs_extra_1.default.writeFile(registryPath, `import { container } from "tsyringe";
15
+ // AUTO-GENERATED MODULE REGISTRATIONS
16
+ `);
17
+ }
18
+ let content = await fs_extra_1.default.readFile(registryPath, "utf-8");
19
+ if (content.includes(`${name}Service`))
20
+ return;
21
+ const importBlock = `import { I${name}Repository } from "./../../Domain/repositories/${moduleName}Repository.interface";
22
+ import { ${name}Repository } from "./../../Infrastructure/repositories/${moduleName}.repository";
23
+ import { I${name}Service } from "./../../Application/interfaces/${moduleName}.service.interface";
24
+ import { ${name}Service } from "./../../Application/services/${moduleName}.service";
25
+ import { ${name}Controller } from "./../controllers/${moduleName}.controller";`;
26
+ const registerBlock = `// ${name}
27
+ container.register<I${name}Repository>("I${name}Repository", { useClass: ${name}Repository });
28
+ container.register<I${name}Service>("I${name}Service", { useClass: ${name}Service });
29
+ container.register<${name}Controller>("${name}Controller", { useClass: ${name}Controller });`;
30
+ content = content.replace('import { container } from "tsyringe";', `import { container } from "tsyringe";\n${importBlock}`);
31
+ content = content.replace("// AUTO-GENERATED MODULE REGISTRATIONS", `// AUTO-GENERATED MODULE REGISTRATIONS\n${registerBlock}`);
32
+ await fs_extra_1.default.writeFile(registryPath, content);
33
+ }
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createOpenApiBase = createOpenApiBase;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ async function createOpenApiBase() {
10
+ const docsPath = path_1.default.join("src", "WebApi", "docs");
11
+ await fs_extra_1.default.ensureDir(docsPath);
12
+ const openApiPath = path_1.default.join(docsPath, "openapi.ts");
13
+ if (await fs_extra_1.default.pathExists(openApiPath)) {
14
+ return;
15
+ }
16
+ const content = `
17
+ export const OpenApiSpecification = {
18
+ openapi: "3.0.0",
19
+ info: {
20
+ title: "My API",
21
+ version: "1.0.0",
22
+ description: "Auto-generated API documentation"
23
+ },
24
+ servers: [
25
+ {
26
+ url: "http://localhost:3000",
27
+ description: "Local server"
28
+ }
29
+ ],
30
+ paths: {},
31
+ components: {
32
+ securitySchemes: {
33
+ BearerAuth: {
34
+ type: "http",
35
+ scheme: "bearer",
36
+ bearerFormat: "JWT"
37
+ }
38
+ },
39
+ schemas: {}
40
+ }
41
+ };
42
+ `;
43
+ await fs_extra_1.default.writeFile(openApiPath, content.trim());
44
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createFile = createFile;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ const ejs_1 = __importDefault(require("ejs"));
10
+ async function createFile(template, destination, data) {
11
+ const templatePath = path_1.default.resolve(__dirname, "../../../templates", template);
12
+ if (await fs_extra_1.default.pathExists(destination)) {
13
+ console.log(`Skipped: ${destination}`);
14
+ return;
15
+ }
16
+ const content = (await ejs_1.default.renderFile(templatePath, data));
17
+ await fs_extra_1.default.writeFile(destination, content);
18
+ console.log(`Created: ${destination}`);
19
+ }
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateModule = generateModule;
7
+ const path_1 = __importDefault(require("path"));
8
+ const structure_1 = require("./structure");
9
+ const baseModel_1 = require("./baseModel");
10
+ const fileCreator_1 = require("./fileCreator");
11
+ const containerRegistry_1 = require("./containerRegistry");
12
+ const routeRegistry_1 = require("./routeRegistry");
13
+ const openApiRegistry_1 = require("./openApiRegistry");
14
+ const createOpenApiBase_1 = require("./createOpenApiBase");
15
+ async function generateModule(name, fields) {
16
+ const moduleName = name.toLowerCase();
17
+ const parsedFields = fields.map((f) => {
18
+ const [fieldName, type] = f.split(":");
19
+ return { fieldName, type };
20
+ });
21
+ const rootPath = path_1.default.join(process.cwd(), "src");
22
+ const { webApiPath, applicationPath, domainPath, infrastructurePath, } = await (0, structure_1.createModuleStructure)(rootPath);
23
+ await (0, baseModel_1.ensureBaseModel)(domainPath);
24
+ // WebApi
25
+ await (0, fileCreator_1.createFile)("controller.ejs", path_1.default.join(webApiPath, "controllers", `${moduleName}.controller.ts`), { name, moduleName, fields: parsedFields });
26
+ await (0, fileCreator_1.createFile)("routes.ejs", path_1.default.join(webApiPath, "routes", `${moduleName}.routes.ts`), { name, fields: parsedFields });
27
+ await (0, fileCreator_1.createFile)("path.ejs", path_1.default.join(webApiPath, "docs", "paths", `${moduleName}.path.ts`), { name, moduleName, fields: parsedFields });
28
+ await (0, fileCreator_1.createFile)("schema.ejs", path_1.default.join(webApiPath, "docs", "schemas", `${moduleName}.schema.ts`), { name, moduleName, fields: parsedFields });
29
+ // Application
30
+ await (0, fileCreator_1.createFile)("dto.ejs", path_1.default.join(applicationPath, "dtos", `${moduleName}.dto.ts`), { name, fields: parsedFields });
31
+ await (0, fileCreator_1.createFile)("service.interface.ejs", path_1.default.join(applicationPath, "interfaces", `${moduleName}.service.interface.ts`), { name, moduleName });
32
+ await (0, fileCreator_1.createFile)("service.impl.ejs", path_1.default.join(applicationPath, "services", `${moduleName}.service.ts`), { name, moduleName });
33
+ // Domain
34
+ await (0, fileCreator_1.createFile)("entity.ejs", path_1.default.join(domainPath, "entities", `${moduleName}.ts`), { name, fields: parsedFields });
35
+ await (0, fileCreator_1.createFile)("repository.interface.ejs", path_1.default.join(domainPath, "repositories", `${moduleName}Repository.interface.ts`), { name, moduleName });
36
+ // Infrastructure
37
+ await (0, fileCreator_1.createFile)("repository.impl.ejs", path_1.default.join(infrastructurePath, "repositories", `${moduleName}.repository.ts`), { name, moduleName });
38
+ await (0, containerRegistry_1.registerModuleInContainer)(webApiPath, name, moduleName);
39
+ (0, routeRegistry_1.registerRouteInMain)(moduleName);
40
+ await (0, createOpenApiBase_1.createOpenApiBase)();
41
+ await (0, openApiRegistry_1.registerOpenApi)(webApiPath, name, moduleName);
42
+ console.log(`Module ${name} created successfully ✔`);
43
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerOpenApi = registerOpenApi;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ //this is to register the generated open api paths and schemas in the main openapi file
10
+ async function registerOpenApi(webApiPath, name, moduleName) {
11
+ const openApiPath = path_1.default.join(webApiPath, "docs", "openapi.ts");
12
+ if (!(await fs_extra_1.default.pathExists(openApiPath)))
13
+ return;
14
+ let content = await fs_extra_1.default.readFile(openApiPath, "utf-8");
15
+ const importPaths = `import { ${name}Paths } from "./paths/${moduleName}.path";`;
16
+ const importSchemas = `import { ${name}Schemas } from "./schemas/${moduleName}.schema";`;
17
+ if (!content.includes(importPaths))
18
+ content = importPaths + "\n" + content;
19
+ if (!content.includes(importSchemas))
20
+ content = importSchemas + "\n" + content;
21
+ if (!content.includes(`...${name}Paths`))
22
+ content = content.replace("paths: {", `paths: {\n ...${name}Paths,`);
23
+ if (!content.includes(`...${name}Schemas`))
24
+ content = content.replace("schemas: {", `schemas: {\n ...${name}Schemas,`);
25
+ await fs_extra_1.default.writeFile(openApiPath, content);
26
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.registerRouteInMain = registerRouteInMain;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ //this register every module's routes in the main application file
9
+ function registerRouteInMain(moduleName) {
10
+ const mainPath = "src/main.ts";
11
+ let content = fs_1.default.readFileSync(mainPath, "utf-8");
12
+ const importLine = `import ${moduleName}Routes from "./WebApi/routes/${moduleName}.routes";`;
13
+ const useLine = `app.use("/${moduleName}", ${moduleName}Routes);`;
14
+ if (!content.includes(importLine)) {
15
+ content = content.replace('import express from "express";', `import express from "express";\n${importLine}`);
16
+ }
17
+ if (!content.includes(useLine)) {
18
+ content = content.replace("app.use(express.json());", `app.use(express.json());\n${useLine}`);
19
+ }
20
+ fs_1.default.writeFileSync(mainPath, content);
21
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createModuleStructure = createModuleStructure;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const path_1 = __importDefault(require("path"));
9
+ //this only creates the folder structure for a module
10
+ async function createModuleStructure(rootPath) {
11
+ //Base folders
12
+ const webApiPath = path_1.default.join(rootPath, "WebApi");
13
+ const applicationPath = path_1.default.join(rootPath, "Application");
14
+ const domainPath = path_1.default.join(rootPath, "Domain");
15
+ const infrastructurePath = path_1.default.join(rootPath, "Infrastructure");
16
+ //subfolders of WebApi
17
+ await fs_extra_1.default.ensureDir(path_1.default.join(webApiPath, "controllers"));
18
+ await fs_extra_1.default.ensureDir(path_1.default.join(webApiPath, "routes"));
19
+ await fs_extra_1.default.ensureDir(path_1.default.join(webApiPath, "docs"));
20
+ await fs_extra_1.default.ensureDir(path_1.default.join(webApiPath, "docs", "paths"));
21
+ await fs_extra_1.default.ensureDir(path_1.default.join(webApiPath, "docs", "schemas"));
22
+ //subfolders of Application
23
+ await fs_extra_1.default.ensureDir(path_1.default.join(applicationPath, "dtos"));
24
+ await fs_extra_1.default.ensureDir(path_1.default.join(applicationPath, "interfaces"));
25
+ await fs_extra_1.default.ensureDir(path_1.default.join(applicationPath, "services"));
26
+ //subfolders of Domain
27
+ await fs_extra_1.default.ensureDir(path_1.default.join(domainPath, "entities"));
28
+ await fs_extra_1.default.ensureDir(path_1.default.join(domainPath, "repositories"));
29
+ //subfolders of Infrastructure
30
+ await fs_extra_1.default.ensureDir(path_1.default.join(infrastructurePath, "repositories"));
31
+ return { webApiPath, applicationPath, domainPath, infrastructurePath };
32
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/index.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const initProject_1 = require("./initializer/initProject");
6
+ const generateModule_1 = require("./generators/module/generateModule");
7
+ const program = new commander_1.Command();
8
+ program
9
+ .name("ddd-backend-cli")
10
+ .version("1.0.0");
11
+ // ==============================
12
+ // INIT PROJECT
13
+ // ==============================
14
+ program
15
+ .command("init <projectName>")
16
+ .description("Initialize a new TypeScript layered project")
17
+ .action(async (projectName) => {
18
+ try {
19
+ await (0, initProject_1.initProject)(projectName);
20
+ }
21
+ catch (error) {
22
+ console.error("Error initializing project:", error);
23
+ }
24
+ });
25
+ // ==============================
26
+ // GENERATE MODULE
27
+ // ==============================
28
+ program
29
+ .command("generate-model <name> [fields...]")
30
+ .description("Generate CRUD module")
31
+ .action(async (name, fields) => {
32
+ try {
33
+ await (0, generateModule_1.generateModule)(name, fields || []);
34
+ }
35
+ catch (error) {
36
+ console.error("Error generating module:", error);
37
+ }
38
+ });
39
+ program.parse(process.argv);
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createBaseStructure = createBaseStructure;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ async function createBaseStructure() {
9
+ //create src folder
10
+ await fs_extra_1.default.ensureDir("src");
11
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createGitignore = createGitignore;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ async function createGitignore() {
9
+ const content = `
10
+ node_modules
11
+ dist
12
+ .env
13
+ `;
14
+ await fs_extra_1.default.writeFile(".gitignore", content.trim());
15
+ }
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createMainFile = createMainFile;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ async function createMainFile() {
9
+ const content = `
10
+ import "reflect-metadata";
11
+ import "./WebApi/container/dependencyContainer";
12
+ import express from "express";
13
+ import { OpenApiSpecification } from "./WebApi/docs/openapi";
14
+ import { apiReference } from "@scalar/express-api-reference";
15
+
16
+ const app = express();
17
+ const PORT = process.env.PORT || 3000;
18
+
19
+ app.use(express.urlencoded({ extended: false }));
20
+ app.use(express.json());
21
+
22
+ app.use(
23
+ "/api-docs",
24
+ apiReference({
25
+ spec: {
26
+ content: OpenApiSpecification,
27
+ },
28
+ })
29
+ );
30
+
31
+ app.listen(PORT, () => {
32
+ console.log(\`Server running on port \${PORT}\`);
33
+ });
34
+ `;
35
+ await fs_extra_1.default.writeFile("src/main.ts", content.trim());
36
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createPackageJson = createPackageJson;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ async function createPackageJson(projectName) {
9
+ const packageJson = {
10
+ name: projectName,
11
+ version: "1.0.0",
12
+ main: "dist/main.js",
13
+ scripts: {
14
+ build: "tsc",
15
+ start: "node dist/main.js",
16
+ dev: "ts-node-dev --respawn src/main.ts",
17
+ },
18
+ };
19
+ await fs_extra_1.default.writeJson("package.json", packageJson, { spaces: 2 });
20
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createTsConfig = createTsConfig;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ async function createTsConfig() {
9
+ const tsconfig = {
10
+ compilerOptions: {
11
+ rootDir: "./src",
12
+ outDir: "./dist",
13
+ module: "Commonjs",
14
+ target: "ES2020",
15
+ lib: ["ES2020"],
16
+ types: ["node"],
17
+ sourceMap: true,
18
+ declaration: true,
19
+ strict: true,
20
+ esModuleInterop: true,
21
+ skipLibCheck: true,
22
+ experimentalDecorators: true,
23
+ emitDecoratorMetadata: true,
24
+ },
25
+ include: ["src"],
26
+ exclude: ["node_modules", "dist"],
27
+ };
28
+ await fs_extra_1.default.writeJson("tsconfig.json", tsconfig, { spaces: 2 });
29
+ }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.initProject = initProject;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_extra_1 = __importDefault(require("fs-extra"));
9
+ const createPackageJson_1 = require("./createPackageJson");
10
+ const createTsConfig_1 = require("./createTsConfig");
11
+ const createGitIgnore_1 = require("./createGitIgnore");
12
+ const createBaseStructure_1 = require("./createBaseStructure");
13
+ const createMainFile_1 = require("./createMainFile");
14
+ const installDependencies_1 = require("./installDependencies");
15
+ async function initProject(projectName) {
16
+ const rootPath = path_1.default.join(process.cwd(), projectName);
17
+ if (await fs_extra_1.default.pathExists(rootPath)) {
18
+ console.log("Project already exists");
19
+ return;
20
+ }
21
+ await fs_extra_1.default.ensureDir(rootPath);
22
+ process.chdir(rootPath);
23
+ await (0, createPackageJson_1.createPackageJson)(projectName);
24
+ await (0, createTsConfig_1.createTsConfig)();
25
+ await (0, createGitIgnore_1.createGitignore)();
26
+ await (0, createBaseStructure_1.createBaseStructure)();
27
+ await (0, createMainFile_1.createMainFile)();
28
+ await (0, installDependencies_1.installDependencies)();
29
+ console.log("Project initialized successfully ✔");
30
+ }
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.installDependencies = installDependencies;
4
+ const child_process_1 = require("child_process");
5
+ async function installDependencies() {
6
+ console.log("Installing dependencies...");
7
+ try {
8
+ (0, child_process_1.execSync)("npm install express tsyringe reflect-metadata @scalar/express-api-reference", { stdio: "inherit" });
9
+ (0, child_process_1.execSync)("npm install -D typescript ts-node-dev @types/node @types/express", { stdio: "inherit" });
10
+ }
11
+ catch {
12
+ console.error("Dependency installation failed");
13
+ }
14
+ }
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "ddd-backend-cli",
3
+ "version": "1.0.0",
4
+ "description": "CLI para generar proyectos backend con DDD",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "ddd-backend-cli": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "keywords": [
13
+ "cli",
14
+ "ddd",
15
+ "backend",
16
+ "generator"
17
+ ],
18
+ "author": "Oscar Molina",
19
+ "license": "MIT",
20
+ "scripts": {
21
+ "build": "tsc",
22
+ "dev": "tsc -w"
23
+ },
24
+ "dependencies": {
25
+ "commander": "^14.0.3",
26
+ "ejs": "^3.1.10",
27
+ "fs-extra": "^11.3.3"
28
+ },
29
+ "devDependencies": {
30
+ "@types/ejs": "^3.1.5",
31
+ "@types/fs-extra": "^11.0.4",
32
+ "@types/node": "^20.11.30",
33
+ "typescript": "^5.3.3"
34
+ }
35
+ }