@saulpaulus17/node-module-generator 2.0.5 โ 3.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 +33 -13
- package/bin/cli.js +17 -6
- package/commands/dto.command.js +3 -3
- package/commands/module.command.js +2 -2
- package/commands/repository.command.js +6 -6
- package/commands/resource.command.js +3 -3
- package/commands/usecase.command.js +2 -2
- package/generator/dto.generator.js +28 -17
- package/generator/module.generator.js +57 -57
- package/generator/repository.generator.js +38 -29
- package/generator/resource.generator.js +56 -56
- package/generator/usecase.generator.js +34 -21
- package/package.json +11 -3
- package/templates/module/controller.test.ejs +1 -1
- package/templates/module/di.ejs +6 -6
- package/templates/module/route.ejs +2 -1
- package/templates/module/usecase.test.ejs +1 -1
- package/utils/case.util.js +24 -7
- package/utils/file.util.js +46 -0
- package/utils/logger.util.js +30 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
- package/.github/ISSUE_TEMPLATE/custom.md +0 -10
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
- package/.github/workflows/ci.yml +0 -28
- package/.github/workflows/release.yml +0 -31
- package/DOCS_STEPS.md +0 -40
- package/release.yml +0 -0
- package/src/modules/Auth/Auth.module.js +0 -15
- package/src/modules/Auth/application/dtos/auth.dto.js +0 -10
- package/src/modules/Auth/application/usecases/AuthUseCase.js +0 -12
- package/src/modules/Auth/application/usecases/AuthUseCase.test.js +0 -30
- package/src/modules/Auth/domain/entities/Auth.js +0 -5
- package/src/modules/Auth/domain/repositories/AuthRepository.js +0 -9
- package/src/modules/Auth/infrastructure/repositories/PrismaAuthRepository.js +0 -15
- package/src/modules/Auth/interfaces/controllers/AuthController.js +0 -15
- package/src/modules/Auth/interfaces/controllers/AuthController.test.js +0 -49
- package/src/modules/Auth/interfaces/routes/auth.routes.js +0 -9
- package/src/modules/Auth/package.json +0 -3
- package/src/modules/order/application/usecases/create-order.usecase.js +0 -15
- package/src/modules/order/application/usecases/create-order.usecase.test.js +0 -26
- package/src/modules/order/domain/entities/order.entity.js +0 -8
- package/src/modules/order/domain/repositories/order.repository.interface.js +0 -11
- package/src/modules/order/infrastructure/repositories/order.repository.impl.js +0 -23
- package/src/modules/order/infrastructure/validation/create-order.schema.js +0 -7
- package/src/modules/order/interfaces/controllers/order.controller.js +0 -16
- package/src/modules/order/interfaces/controllers/order.controller.test.js +0 -46
- package/src/modules/order/interfaces/routes/order.routes.js +0 -9
- package/src/modules/order/order.module.js +0 -16
- package/src/modules/product/application/usecases/getProduct.usecase.js +0 -15
- package/src/modules/product/application/usecases/getProduct.usecase.test.js +0 -26
- package/src/modules/product/domain/entities/product.entity.js +0 -8
- package/src/modules/product/domain/repositories/product.repository.interface.js +0 -11
- package/src/modules/product/infrastructure/repositories/product.repository.impl.js +0 -23
- package/src/modules/product/infrastructure/validation/getProduct.schema.js +0 -7
- package/src/modules/product/product.module.js +0 -5
- package/src/modules/user/application/usecases/create-user.usecase.js +0 -15
- package/src/modules/user/application/usecases/create-user.usecase.test.js +0 -26
- package/src/modules/user/domain/entities/user.entity.js +0 -8
- package/src/modules/user/domain/repositories/user.repository.interface.js +0 -11
- package/src/modules/user/infrastructure/repositories/user.repository.impl.js +0 -23
- package/src/modules/user/infrastructure/validation/create-user.schema.js +0 -7
- package/src/modules/user/interfaces/controllers/user.controller.js +0 -16
- package/src/modules/user/interfaces/controllers/user.controller.test.js +0 -46
- package/src/modules/user/interfaces/routes/user.routes.js +0 -9
- package/src/modules/user/user.module.js +0 -16
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="
|
|
2
|
+
<img src="./assets/banner.png" alt="Node Module Generator Banner" width="600" style="max-width: 100%;" />
|
|
3
3
|
<h1>๐ Node Module Generator (NMG)</h1>
|
|
4
4
|
<p><strong>The ultimate CLI companion for rapid, enterprise-grade Node.js scaffolding.</strong></p>
|
|
5
5
|
<p>
|
|
@@ -49,7 +49,7 @@ graph TD
|
|
|
49
49
|
- ๐ **Clean Architecture by Design**: Strict separation into Domain, Application, Infrastructure, and Interface layers.
|
|
50
50
|
- ๐ **Native Dependency Injection**: Fully pre-configured for **Awilix**, providing seamless DI management.
|
|
51
51
|
- ๐งช **Test-Ready Scaffolding**: Automatically generates **Jest** test suites for Controllers and Use Cases.
|
|
52
|
-
- ๐ **
|
|
52
|
+
- ๐ **Full ESM Support**: Native support for **ECMAScript Modules (ESM)** with consistent **kebab-case** file naming.
|
|
53
53
|
- ๐ค **Granular Control**: Generate full modules or individual components (UseCases, Repos, DTOs) without disrupting existing code.
|
|
54
54
|
|
|
55
55
|
---
|
|
@@ -76,6 +76,25 @@ npx @saulpaulus17/node-module-generator <command> <name>
|
|
|
76
76
|
|
|
77
77
|
---
|
|
78
78
|
|
|
79
|
+
## ๐ ๏ธ Target Project Dependencies
|
|
80
|
+
|
|
81
|
+
To ensure the modules generated by NMG function correctly, your main project must have the following core dependencies installed:
|
|
82
|
+
|
|
83
|
+
### Production Dependencies
|
|
84
|
+
```bash
|
|
85
|
+
npm install express awilix @prisma/client
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Development Dependencies
|
|
89
|
+
```bash
|
|
90
|
+
npm install --save-dev jest
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
> [!TIP]
|
|
94
|
+
> These dependencies are essential because the generated code relies on Express for routing, Awilix for Dependency Injection, and Prisma for the data layer.
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
79
98
|
## ๐ Detailed Usage
|
|
80
99
|
|
|
81
100
|
### 1. Generating a Full Module
|
|
@@ -108,25 +127,25 @@ Scaffolding a module (e.g., `nmg module Product`) produces the following industr
|
|
|
108
127
|
```text
|
|
109
128
|
src/modules/Product/
|
|
110
129
|
โโโ application/
|
|
111
|
-
โ โโโ dtos/ # DTO schemas (e.g., product
|
|
130
|
+
โ โโโ dtos/ # DTO schemas (e.g., product-dto.js)
|
|
112
131
|
โ โโโ usecases/ # Business orchestration
|
|
113
|
-
โ โโโ
|
|
114
|
-
โ โโโ
|
|
132
|
+
โ โโโ product-use-case.js # Logic implementation
|
|
133
|
+
โ โโโ product-use-case.test.js # Unit tests
|
|
115
134
|
โโโ domain/
|
|
116
135
|
โ โโโ entities/ # Business entity definitions
|
|
117
|
-
โ โ โโโ
|
|
136
|
+
โ โ โโโ product-entity.js
|
|
118
137
|
โ โโโ repositories/ # Repository Interface (Contracts)
|
|
119
|
-
โ โโโ
|
|
138
|
+
โ โโโ product-repository.js
|
|
120
139
|
โโโ infrastructure/
|
|
121
140
|
โ โโโ repositories/ # Implementation (default: Prisma)
|
|
122
|
-
โ โ โโโ
|
|
141
|
+
โ โ โโโ prisma-product-repository.js
|
|
123
142
|
โโโ interfaces/
|
|
124
143
|
โ โโโ controllers/ # Express handlers
|
|
125
|
-
โ โ โโโ
|
|
126
|
-
โ โ โโโ
|
|
144
|
+
โ โ โโโ product-controller.js
|
|
145
|
+
โ โ โโโ product-controller.test.js
|
|
127
146
|
โ โโโ routes/ # Express routes & method binding
|
|
128
|
-
โ โโโ product
|
|
129
|
-
โโโ
|
|
147
|
+
โ โโโ product-routes.js
|
|
148
|
+
โโโ product.module.js # Central Awilix Module Registration
|
|
130
149
|
```
|
|
131
150
|
|
|
132
151
|
---
|
|
@@ -138,7 +157,8 @@ To finalize your new module integration, follow these standard steps:
|
|
|
138
157
|
1. **DI Registration**: Open `src/container.js` and register any specific repository aliases or scoped usecases.
|
|
139
158
|
2. **Route Mounting**: Mount the generated router in `src/app.js`:
|
|
140
159
|
```javascript
|
|
141
|
-
|
|
160
|
+
import productRoutes from './modules/Product/interfaces/routes/product-routes.js';
|
|
161
|
+
app.use('/api/v1/product', productRoutes);
|
|
142
162
|
```
|
|
143
163
|
3. **Detailed Implementation**: Build out the specific logic in the generated templates (which are already integrated via Awilix).
|
|
144
164
|
|
package/bin/cli.js
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import moduleCommand from "../commands/module.command.js";
|
|
5
|
+
import usecaseCommand from "../commands/usecase.command.js";
|
|
6
|
+
import resourceCommand from "../commands/resource.command.js";
|
|
7
|
+
import repositoryCommand from "../commands/repository.command.js";
|
|
8
|
+
import dtoCommand from "../commands/dto.command.js";
|
|
9
|
+
|
|
4
10
|
const program = new Command();
|
|
5
11
|
|
|
6
12
|
program.name("nmg").version("1.0.0").description("Clean nodejs CLI");
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
process.on("unhandledRejection", (err) => {
|
|
15
|
+
console.error("โ FATAL ERROR: ", err.stack || err);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
moduleCommand(program);
|
|
20
|
+
usecaseCommand(program);
|
|
21
|
+
resourceCommand(program);
|
|
22
|
+
repositoryCommand(program);
|
|
23
|
+
dtoCommand(program);
|
|
13
24
|
|
|
14
25
|
program.parse();
|
package/commands/dto.command.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import generateDto from "../generator/dto.generator.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default (program) => {
|
|
4
4
|
program
|
|
5
5
|
.command("dto <name>")
|
|
6
|
-
.description("Create a new DTO
|
|
6
|
+
.description("Create a new DTO inside an existing module")
|
|
7
7
|
.option("-m, --module <moduleName>", "Specify the target module")
|
|
8
8
|
.action((name, options) => {
|
|
9
9
|
if (!options.module) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import generateModule from "../generator/module.generator.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default (program) => {
|
|
4
4
|
program
|
|
5
5
|
.command("module <name>")
|
|
6
6
|
.description("Create a new module")
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
import generateRepository from "../generator/repository.generator.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default (program) => {
|
|
4
4
|
program
|
|
5
|
-
.command("repository <
|
|
6
|
-
.description("Create
|
|
7
|
-
.action((
|
|
8
|
-
generateRepository(
|
|
5
|
+
.command("repository <name>")
|
|
6
|
+
.description("Create a new repository inside an existing module")
|
|
7
|
+
.action((name) => {
|
|
8
|
+
generateRepository(name);
|
|
9
9
|
});
|
|
10
10
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import generateResource from "../generator/resource.generator.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default (program) => {
|
|
4
4
|
program
|
|
5
5
|
.command("resource <name>")
|
|
6
|
-
.description("Create a
|
|
6
|
+
.description("Create a complete resource (CRUD)")
|
|
7
7
|
.action((name) => {
|
|
8
8
|
generateResource(name);
|
|
9
9
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
import generateUsecase from "../generator/usecase.generator.js";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default (program) => {
|
|
4
4
|
program
|
|
5
5
|
.command("usecase <name>")
|
|
6
6
|
.description("Create a new usecase inside an existing module")
|
|
@@ -1,21 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pascalCase, camelCase, kebabCase } from "../utils/case.util.js";
|
|
3
|
+
import FileUtil from "../utils/file.util.js";
|
|
4
|
+
import Logger from "../utils/logger.util.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export default async function (schemaName, moduleName) {
|
|
7
|
+
try {
|
|
8
|
+
Logger.info(`Starting generation for DTO: ${schemaName} in module: ${moduleName}`);
|
|
9
|
+
const basePath = path.join(process.cwd(), "src/modules", moduleName);
|
|
10
|
+
const dtoDir = "application/dtos";
|
|
11
|
+
|
|
12
|
+
FileUtil.ensureDirectories(basePath, [dtoDir]);
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const templateData = {
|
|
15
|
+
name: moduleName,
|
|
16
|
+
className: pascalCase(schemaName),
|
|
17
|
+
camelName: camelCase(moduleName),
|
|
18
|
+
kebabName: kebabCase(schemaName),
|
|
19
|
+
};
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
21
|
+
await FileUtil.renderAndWrite(
|
|
22
|
+
"module/dto.ejs",
|
|
23
|
+
templateData,
|
|
24
|
+
path.join(basePath, dtoDir, `${kebabCase(schemaName)}-dto.js`)
|
|
25
|
+
);
|
|
19
26
|
|
|
20
|
-
|
|
21
|
-
}
|
|
27
|
+
Logger.success(`DTO ${schemaName} generated inside module ${moduleName} at application/dtos.`);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
Logger.error(`Failed to generate DTO ${schemaName}`, error);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -1,57 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pascalCase, camelCase, kebabCase } from "../utils/case.util.js";
|
|
3
|
+
import FileUtil from "../utils/file.util.js";
|
|
4
|
+
import Logger from "../utils/logger.util.js";
|
|
5
|
+
|
|
6
|
+
export default async function (name) {
|
|
7
|
+
try {
|
|
8
|
+
Logger.info(`Starting generation for module: ${name}`);
|
|
9
|
+
const basePath = path.join(process.cwd(), "src/modules", name);
|
|
10
|
+
|
|
11
|
+
const dirs = [
|
|
12
|
+
"domain/entities",
|
|
13
|
+
"domain/repositories",
|
|
14
|
+
"application/usecases",
|
|
15
|
+
"application/dtos",
|
|
16
|
+
"infrastructure/repositories",
|
|
17
|
+
"interfaces/controllers",
|
|
18
|
+
"interfaces/routes",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
// Create directories
|
|
22
|
+
FileUtil.ensureDirectories(basePath, dirs);
|
|
23
|
+
|
|
24
|
+
const templateData = {
|
|
25
|
+
name,
|
|
26
|
+
className: pascalCase(name),
|
|
27
|
+
camelName: camelCase(name),
|
|
28
|
+
kebabName: kebabCase(name),
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const filesToGenerate = [
|
|
32
|
+
{ tpl: "module/controller.ejs", out: `interfaces/controllers/${kebabCase(name)}-controller.js` },
|
|
33
|
+
{ tpl: "module/controller.test.ejs", out: `interfaces/controllers/${kebabCase(name)}-controller.test.js` },
|
|
34
|
+
{ tpl: "module/route.ejs", out: `interfaces/routes/${kebabCase(name)}-routes.js` },
|
|
35
|
+
{ tpl: "module/usecase.ejs", out: `application/usecases/${kebabCase(name)}-use-case.js` },
|
|
36
|
+
{ tpl: "module/usecase.test.ejs", out: `application/usecases/${kebabCase(name)}-use-case.test.js` },
|
|
37
|
+
{ tpl: "module/entity.ejs", out: `domain/entities/${kebabCase(name)}-entity.js` },
|
|
38
|
+
{ tpl: "module/repository.interface.ejs", out: `domain/repositories/${kebabCase(name)}-repository.js` },
|
|
39
|
+
{ tpl: "module/repository.impl.ejs", out: `infrastructure/repositories/prisma-${kebabCase(name)}-repository.js` },
|
|
40
|
+
{ tpl: "module/dto.ejs", out: `application/dtos/${kebabCase(name)}-dto.js` },
|
|
41
|
+
{ tpl: "module/di.ejs", out: `${kebabCase(name)}.module.js` }
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
for (const file of filesToGenerate) {
|
|
45
|
+
await FileUtil.renderAndWrite(
|
|
46
|
+
file.tpl,
|
|
47
|
+
templateData,
|
|
48
|
+
path.join(basePath, file.out)
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
Logger.success(`Module ${name} generated successfully!`);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
Logger.error(`Failed to generate module ${name}`, error);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -1,36 +1,45 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pascalCase, camelCase, kebabCase } from "../utils/case.util.js";
|
|
3
|
+
import FileUtil from "../utils/file.util.js";
|
|
4
|
+
import Logger from "../utils/logger.util.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
export default async function (moduleName) {
|
|
7
|
+
try {
|
|
8
|
+
Logger.info(`Starting repository pattern generation for module: ${moduleName}`);
|
|
9
|
+
const basePath = path.join(process.cwd(), "src/modules", moduleName);
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
const dirs = [
|
|
12
|
+
"domain/entities",
|
|
13
|
+
"domain/repositories",
|
|
14
|
+
"infrastructure/repositories",
|
|
15
|
+
];
|
|
12
16
|
|
|
13
|
-
|
|
14
|
-
fs.ensureDirSync(repoInterfaceDir);
|
|
15
|
-
fs.ensureDirSync(repoImplDir);
|
|
17
|
+
FileUtil.ensureDirectories(basePath, dirs);
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
const templateData = {
|
|
20
|
+
name: moduleName,
|
|
21
|
+
className: pascalCase(moduleName),
|
|
22
|
+
camelName: camelCase(moduleName),
|
|
23
|
+
kebabName: kebabCase(moduleName),
|
|
24
|
+
};
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
fs.writeFileSync(path.join(basePath, outputPath), templateContent);
|
|
29
|
-
};
|
|
26
|
+
const filesToGenerate = [
|
|
27
|
+
{ tpl: "module/entity.ejs", out: `domain/entities/${kebabCase(moduleName)}-entity.js` },
|
|
28
|
+
{ tpl: "module/repository.interface.ejs", out: `domain/repositories/${kebabCase(moduleName)}-repository.js` },
|
|
29
|
+
{ tpl: "module/repository.impl.ejs", out: `infrastructure/repositories/prisma-${kebabCase(moduleName)}-repository.js` }
|
|
30
|
+
];
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
for (const file of filesToGenerate) {
|
|
33
|
+
await FileUtil.renderAndWrite(
|
|
34
|
+
file.tpl,
|
|
35
|
+
templateData,
|
|
36
|
+
path.join(basePath, file.out)
|
|
37
|
+
);
|
|
38
|
+
}
|
|
34
39
|
|
|
35
|
-
|
|
36
|
-
}
|
|
40
|
+
Logger.success(`Repository patterns for ${moduleName} generated successfully.`);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
Logger.error(`Failed to generate repository patterns for ${moduleName}`, error);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pascalCase, camelCase, kebabCase } from "../utils/case.util.js";
|
|
3
|
+
import FileUtil from "../utils/file.util.js";
|
|
4
|
+
import Logger from "../utils/logger.util.js";
|
|
5
|
+
|
|
6
|
+
export default async function (name) {
|
|
7
|
+
try {
|
|
8
|
+
Logger.info(`Starting generation for resource: ${name}`);
|
|
9
|
+
const basePath = path.join(process.cwd(), "src/modules", name);
|
|
10
|
+
|
|
11
|
+
const dirs = [
|
|
12
|
+
"domain/entities",
|
|
13
|
+
"domain/repositories",
|
|
14
|
+
"application/usecases",
|
|
15
|
+
"application/dtos",
|
|
16
|
+
"infrastructure/repositories",
|
|
17
|
+
"interfaces/controllers",
|
|
18
|
+
"interfaces/routes",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
FileUtil.ensureDirectories(basePath, dirs);
|
|
22
|
+
|
|
23
|
+
const templateData = {
|
|
24
|
+
name,
|
|
25
|
+
className: pascalCase(name),
|
|
26
|
+
camelName: camelCase(name),
|
|
27
|
+
kebabName: kebabCase(name),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const filesToGenerate = [
|
|
31
|
+
{ tpl: "module/controller.ejs", out: `interfaces/controllers/${kebabCase(name)}-controller.js` },
|
|
32
|
+
{ tpl: "module/controller.test.ejs", out: `interfaces/controllers/${kebabCase(name)}-controller.test.js` },
|
|
33
|
+
{ tpl: "module/route.ejs", out: `interfaces/routes/${kebabCase(name)}-routes.js` },
|
|
34
|
+
{ tpl: "module/usecase.ejs", out: `application/usecases/${kebabCase(name)}-use-case.js` },
|
|
35
|
+
{ tpl: "module/usecase.test.ejs", out: `application/usecases/${kebabCase(name)}-use-case.test.js` },
|
|
36
|
+
{ tpl: "module/entity.ejs", out: `domain/entities/${kebabCase(name)}-entity.js` },
|
|
37
|
+
{ tpl: "module/repository.interface.ejs", out: `domain/repositories/${kebabCase(name)}-repository.js` },
|
|
38
|
+
{ tpl: "module/repository.impl.ejs", out: `infrastructure/repositories/prisma-${kebabCase(name)}-repository.js` },
|
|
39
|
+
{ tpl: "module/dto.ejs", out: `application/dtos/${kebabCase(name)}-dto.js` },
|
|
40
|
+
{ tpl: "module/di.ejs", out: `${kebabCase(name)}.module.js` }
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
for (const file of filesToGenerate) {
|
|
44
|
+
await FileUtil.renderAndWrite(
|
|
45
|
+
file.tpl,
|
|
46
|
+
templateData,
|
|
47
|
+
path.join(basePath, file.out)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
Logger.success(`Resource ${name} generated successfully with Clean Architecture and Awilix DI!`);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
Logger.error(`Failed to generate resource ${name}`, error);
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -1,26 +1,39 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { pascalCase, camelCase, kebabCase } from "../utils/case.util.js";
|
|
3
|
+
import FileUtil from "../utils/file.util.js";
|
|
4
|
+
import Logger from "../utils/logger.util.js";
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
export default async function (useCaseName, moduleName) {
|
|
7
|
+
try {
|
|
8
|
+
Logger.info(`Starting usecase generation: ${useCaseName} in module: ${moduleName}`);
|
|
9
|
+
const basePath = path.join(process.cwd(), "src/modules", moduleName);
|
|
10
|
+
const ucDir = "application/usecases";
|
|
11
|
+
|
|
12
|
+
FileUtil.ensureDirectories(basePath, [ucDir]);
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
const templateData = {
|
|
15
|
+
name: moduleName,
|
|
16
|
+
className: pascalCase(useCaseName),
|
|
17
|
+
camelName: camelCase(moduleName),
|
|
18
|
+
kebabName: kebabCase(useCaseName),
|
|
19
|
+
moduleKebabName: kebabCase(moduleName),
|
|
20
|
+
};
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
await FileUtil.renderAndWrite(
|
|
23
|
+
"module/usecase.ejs",
|
|
24
|
+
templateData,
|
|
25
|
+
path.join(basePath, ucDir, `${kebabCase(useCaseName)}-use-case.js`)
|
|
26
|
+
);
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
await FileUtil.renderAndWrite(
|
|
29
|
+
"module/usecase.test.ejs",
|
|
30
|
+
templateData,
|
|
31
|
+
path.join(basePath, ucDir, `${kebabCase(useCaseName)}-use-case.test.js`)
|
|
32
|
+
);
|
|
24
33
|
|
|
25
|
-
|
|
26
|
-
}
|
|
34
|
+
Logger.success(`Usecase ${useCaseName} generated inside module ${moduleName}.`);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
Logger.error(`Failed to generate usecase ${useCaseName}`, error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|