Skip to content

Commit b3f8888

Browse files
committed
fix: Align Module Generator with Clean Architecture Flow
1 parent 166a17d commit b3f8888

13 files changed

Lines changed: 49 additions & 87 deletions

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ Scaffold specifically what you need, exactly how you do it in NestJS:
5757
# 1. Scaffolds a new module architecture and empty DI registry
5858
nmg module product
5959

60+
6061
# 2. Creates a specific Use Case and its Test inside an existing module
6162
nmg usecase updateProduct --module=product
6263

bin/cli.js

100644100755
File mode changed.

generator/module.generator.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ module.exports = async function (name) {
99
const dirs = [
1010
"domain/entities",
1111
"domain/repositories",
12-
"domain/services",
1312
"application/usecases",
1413
"application/dtos",
1514
"infrastructure/repositories",
16-
"infrastructure/validation",
17-
"infrastructure/security",
18-
"infrastructure/services",
1915
"interfaces/controllers",
2016
"interfaces/routes",
2117
];

generator/repository.generator.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ module.exports = async function (moduleName) {
2828
fs.writeFileSync(path.join(basePath, outputPath), templateContent);
2929
};
3030

31-
await renderAndWrite("entity.ejs", `domain/entities/${moduleName}.entity.js`);
32-
await renderAndWrite("repository.interface.ejs", `domain/repositories/${moduleName}.repository.interface.js`);
33-
await renderAndWrite("repository.impl.ejs", `infrastructure/repositories/${moduleName}.repository.impl.js`);
31+
await renderAndWrite("entity.ejs", `domain/entities/${pascalCase(moduleName)}.js`);
32+
await renderAndWrite("repository.interface.ejs", `domain/repositories/${pascalCase(moduleName)}Repository.js`);
33+
await renderAndWrite("repository.impl.ejs", `infrastructure/repositories/Prisma${pascalCase(moduleName)}Repository.js`);
3434

3535
console.log(`✔ Repository patterns for ${moduleName} generated successfully.`);
3636
};

generator/resource.generator.js

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ module.exports = async function (name) {
99
const dirs = [
1010
"domain/entities",
1111
"domain/repositories",
12-
"domain/services",
1312
"application/usecases",
1413
"application/dtos",
1514
"infrastructure/repositories",
16-
"infrastructure/validation",
17-
"infrastructure/security",
18-
"infrastructure/services",
1915
"interfaces/controllers",
2016
"interfaces/routes",
2117
];
@@ -27,7 +23,7 @@ module.exports = async function (name) {
2723
className: pascalCase(name),
2824
camelName: camelCase(name),
2925
useCaseClassName: `Create${pascalCase(name)}UseCase`,
30-
useCaseFileName: `create-${name}`,
26+
useCaseFileName: `Create${pascalCase(name)}UseCase`,
3127
};
3228

3329
const renderAndWrite = async (templateName, outputPath) => {
@@ -38,18 +34,18 @@ module.exports = async function (name) {
3834
fs.writeFileSync(path.join(basePath, outputPath), templateContent);
3935
};
4036

41-
await renderAndWrite("controller.ejs", `interfaces/controllers/${name}.controller.js`);
42-
await renderAndWrite("controller.test.ejs", `interfaces/controllers/${name}.controller.test.js`);
43-
await renderAndWrite("route.ejs", `interfaces/routes/${name}.routes.js`);
37+
await renderAndWrite("controller.ejs", `interfaces/controllers/${pascalCase(name)}Controller.js`);
38+
await renderAndWrite("controller.test.ejs", `interfaces/controllers/${pascalCase(name)}Controller.test.js`);
39+
await renderAndWrite("route.ejs", `interfaces/routes/${name.toLowerCase()}.routes.js`);
4440

45-
await renderAndWrite("usecase.ejs", `application/usecases/create-${name}.usecase.js`);
46-
await renderAndWrite("usecase.test.ejs", `application/usecases/create-${name}.usecase.test.js`);
41+
await renderAndWrite("usecase.ejs", `application/usecases/Create${pascalCase(name)}UseCase.js`);
42+
await renderAndWrite("usecase.test.ejs", `application/usecases/Create${pascalCase(name)}UseCase.test.js`);
4743

48-
await renderAndWrite("entity.ejs", `domain/entities/${name}.entity.js`);
49-
await renderAndWrite("repository.interface.ejs", `domain/repositories/${name}.repository.interface.js`);
44+
await renderAndWrite("entity.ejs", `domain/entities/${pascalCase(name)}.js`);
45+
await renderAndWrite("repository.interface.ejs", `domain/repositories/${pascalCase(name)}Repository.js`);
5046

51-
await renderAndWrite("repository.impl.ejs", `infrastructure/repositories/${name}.repository.impl.js`);
52-
await renderAndWrite("dto.ejs", `infrastructure/validation/create-${name}.schema.js`);
47+
await renderAndWrite("repository.impl.ejs", `infrastructure/repositories/Prisma${pascalCase(name)}Repository.js`);
48+
await renderAndWrite("dto.ejs", `application/dtos/${name.toLowerCase()}.dto.js`);
5349

5450
await renderAndWrite("di.ejs", `${name}.module.js`);
5551

generator/usecase.generator.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ module.exports = async function (useCaseName, moduleName) {
1717
};
1818

1919
const templateContent = await ejs.renderFile(path.join(__dirname, "../templates/module/usecase.ejs"), templateData);
20-
fs.writeFileSync(path.join(ucDir, `${useCaseName}.usecase.js`), templateContent);
20+
fs.writeFileSync(path.join(ucDir, `${pascalCase(useCaseName)}UseCase.js`), templateContent);
2121

2222
const testContent = await ejs.renderFile(path.join(__dirname, "../templates/module/usecase.test.ejs"), templateData);
23-
fs.writeFileSync(path.join(ucDir, `${useCaseName}.usecase.test.js`), testContent);
23+
fs.writeFileSync(path.join(ucDir, `${pascalCase(useCaseName)}UseCase.test.js`), testContent);
2424

2525
console.log(`✔ Usecase ${useCaseName} generated inside module ${moduleName}.`);
2626
};

templates/module/controller.ejs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
1-
class <%= className %>Controller {
2-
constructor({ <%= camelName %>UseCase }) {
3-
this.<%= camelName %>UseCase = <%= camelName %>UseCase;
1+
export default class <%= className %>Controller {
2+
constructor({ <%= camelName %>Repository }) {
3+
this.<%= camelName %>Repository = <%= camelName %>Repository;
44
}
55

6-
create = async (req, res, next) => {
6+
async findById(req, res, next) {
77
try {
8-
const result = await this.<%= camelName %>UseCase.execute(req.body);
9-
res.status(201).json({ success: true, data: result });
8+
const result = await this.<%= camelName %>Repository.findById(req.params.id);
9+
res.json(result);
1010
} catch (error) {
1111
next(error);
1212
}
13-
};
13+
}
1414
}
15-
16-
module.exports = <%= className %>Controller;

templates/module/di.ejs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
const { asClass, asFunction } = require('awilix');
1+
import { asClass, asFunction } from 'awilix';
22

3-
const <%= className %>Controller = require('./interfaces/controllers/<%= name %>.controller');
4-
const create<%= className %>Routes = require('./interfaces/routes/<%= name %>.routes');
5-
const Create<%= className %>UseCase = require('./application/usecases/create-<%= name %>.usecase');
6-
const <%= className %>Repository = require('./infrastructure/repositories/<%= name %>.repository.impl');
3+
import <%= className %>Controller from './interfaces/controllers/<%= className %>Controller';
4+
import create<%= className %>Routes from './interfaces/routes/<%= name.toLowerCase() %>.routes';
5+
import Create<%= className %>UseCase from './application/usecases/Create<%= className %>UseCase';
6+
import Prisma<%= className %>Repository from './infrastructure/repositories/Prisma<%= className %>Repository';
77

8-
module.exports = function register<%= className %>Module(container) {
8+
export default function register<%= className %>Module(container) {
99
container.register({
1010
<%= camelName %>Controller: asClass(<%= className %>Controller).singleton(),
1111
<%= camelName %>Routes: asFunction(create<%= className %>Routes).singleton(),
12-
<%= camelName %>UseCase: asClass(Create<%= className %>UseCase).singleton(),
13-
// Providing the interface's name as the injection token for the implementation
14-
<%= camelName %>Repository: asClass(<%= className %>Repository).singleton(),
12+
Create<%= className %>UseCase: asClass(Create<%= className %>UseCase).singleton(),
13+
<%= camelName %>Repository: asFunction(({ prisma<%= className %>Repository }) => prisma<%= className %>Repository).scoped(),
1514
});
16-
};
15+
}

templates/module/entity.ejs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
class <%= className %>Entity {
2-
constructor({ id, ...props }) {
3-
this.id = id;
1+
export default class <%= className %> {
2+
constructor(props) {
43
Object.assign(this, props);
54
}
65
}
7-
8-
module.exports = <%= className %>Entity;
Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,11 @@
1-
const I<%= className %>Repository = require('../../domain/repositories/<%= name %>.repository.interface');
2-
const <%= className %>Entity = require('../../domain/entities/<%= name %>.entity');
3-
4-
class <%= className %>RepositoryImpl extends I<%= className %>Repository {
5-
// If using Prisma, you would do: constructor({ prisma }) { super(); this.prisma = prisma; }
6-
constructor() {
7-
super();
8-
this.db = new Map();
9-
}
10-
11-
async save(dto) {
12-
const id = Date.now().toString(); // Mock ID generation
13-
const entity = new <%= className %>Entity({ id, ...dto });
14-
this.db.set(id, entity);
15-
return entity;
1+
export default class Prisma<%= className %>Repository {
2+
constructor({ prisma }) {
3+
this.prisma = prisma;
164
}
175

186
async findById(id) {
19-
return this.db.get(id) || null;
7+
return this.prisma.<%= camelName %>s.findUnique({
8+
where: { id },
9+
});
2010
}
2111
}
22-
23-
module.exports = <%= className %>RepositoryImpl;

0 commit comments

Comments
 (0)