@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.
Files changed (65) hide show
  1. package/README.md +33 -13
  2. package/bin/cli.js +17 -6
  3. package/commands/dto.command.js +3 -3
  4. package/commands/module.command.js +2 -2
  5. package/commands/repository.command.js +6 -6
  6. package/commands/resource.command.js +3 -3
  7. package/commands/usecase.command.js +2 -2
  8. package/generator/dto.generator.js +28 -17
  9. package/generator/module.generator.js +57 -57
  10. package/generator/repository.generator.js +38 -29
  11. package/generator/resource.generator.js +56 -56
  12. package/generator/usecase.generator.js +34 -21
  13. package/package.json +11 -3
  14. package/templates/module/controller.test.ejs +1 -1
  15. package/templates/module/di.ejs +6 -6
  16. package/templates/module/route.ejs +2 -1
  17. package/templates/module/usecase.test.ejs +1 -1
  18. package/utils/case.util.js +24 -7
  19. package/utils/file.util.js +46 -0
  20. package/utils/logger.util.js +30 -0
  21. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -38
  22. package/.github/ISSUE_TEMPLATE/custom.md +0 -10
  23. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -20
  24. package/.github/workflows/ci.yml +0 -28
  25. package/.github/workflows/release.yml +0 -31
  26. package/DOCS_STEPS.md +0 -40
  27. package/release.yml +0 -0
  28. package/src/modules/Auth/Auth.module.js +0 -15
  29. package/src/modules/Auth/application/dtos/auth.dto.js +0 -10
  30. package/src/modules/Auth/application/usecases/AuthUseCase.js +0 -12
  31. package/src/modules/Auth/application/usecases/AuthUseCase.test.js +0 -30
  32. package/src/modules/Auth/domain/entities/Auth.js +0 -5
  33. package/src/modules/Auth/domain/repositories/AuthRepository.js +0 -9
  34. package/src/modules/Auth/infrastructure/repositories/PrismaAuthRepository.js +0 -15
  35. package/src/modules/Auth/interfaces/controllers/AuthController.js +0 -15
  36. package/src/modules/Auth/interfaces/controllers/AuthController.test.js +0 -49
  37. package/src/modules/Auth/interfaces/routes/auth.routes.js +0 -9
  38. package/src/modules/Auth/package.json +0 -3
  39. package/src/modules/order/application/usecases/create-order.usecase.js +0 -15
  40. package/src/modules/order/application/usecases/create-order.usecase.test.js +0 -26
  41. package/src/modules/order/domain/entities/order.entity.js +0 -8
  42. package/src/modules/order/domain/repositories/order.repository.interface.js +0 -11
  43. package/src/modules/order/infrastructure/repositories/order.repository.impl.js +0 -23
  44. package/src/modules/order/infrastructure/validation/create-order.schema.js +0 -7
  45. package/src/modules/order/interfaces/controllers/order.controller.js +0 -16
  46. package/src/modules/order/interfaces/controllers/order.controller.test.js +0 -46
  47. package/src/modules/order/interfaces/routes/order.routes.js +0 -9
  48. package/src/modules/order/order.module.js +0 -16
  49. package/src/modules/product/application/usecases/getProduct.usecase.js +0 -15
  50. package/src/modules/product/application/usecases/getProduct.usecase.test.js +0 -26
  51. package/src/modules/product/domain/entities/product.entity.js +0 -8
  52. package/src/modules/product/domain/repositories/product.repository.interface.js +0 -11
  53. package/src/modules/product/infrastructure/repositories/product.repository.impl.js +0 -23
  54. package/src/modules/product/infrastructure/validation/getProduct.schema.js +0 -7
  55. package/src/modules/product/product.module.js +0 -5
  56. package/src/modules/user/application/usecases/create-user.usecase.js +0 -15
  57. package/src/modules/user/application/usecases/create-user.usecase.test.js +0 -26
  58. package/src/modules/user/domain/entities/user.entity.js +0 -8
  59. package/src/modules/user/domain/repositories/user.repository.interface.js +0 -11
  60. package/src/modules/user/infrastructure/repositories/user.repository.impl.js +0 -23
  61. package/src/modules/user/infrastructure/validation/create-user.schema.js +0 -7
  62. package/src/modules/user/interfaces/controllers/user.controller.js +0 -16
  63. package/src/modules/user/interfaces/controllers/user.controller.test.js +0 -46
  64. package/src/modules/user/interfaces/routes/user.routes.js +0 -9
  65. package/src/modules/user/user.module.js +0 -16
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saulpaulus17/node-module-generator",
3
- "version": "2.0.5",
3
+ "version": "3.0.0",
4
4
  "description": "CLI tool to grenerate modular scaffolding for nodejs projects following clean arsitecture principles. ",
5
5
  "keywords": [
6
6
  "nodejs",
@@ -10,7 +10,15 @@
10
10
  ],
11
11
  "license": "MIT",
12
12
  "author": "saul-paulus (ixspx)",
13
- "type": "commonjs",
13
+ "type": "module",
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/saul-paulus/node-module-generator.git"
17
+ },
18
+ "bugs": {
19
+ "url": "https://github.com/saul-paulus/node-module-generator/issues"
20
+ },
21
+ "homepage": "https://github.com/saul-paulus/node-module-generator#readme",
14
22
  "main": "index.js",
15
23
  "bin": {
16
24
  "nmg": "./bin/cli.js"
@@ -19,7 +27,7 @@
19
27
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
20
28
  },
21
29
  "dependencies": {
22
- "chalk": "^5.6.2",
30
+ "chalk": "^4.1.2",
23
31
  "commander": "^14.0.3",
24
32
  "ejs": "^5.0.1",
25
33
  "fs-extra": "^11.3.4"
@@ -1,5 +1,5 @@
1
1
  import { jest, describe, it, expect, beforeEach } from '@jest/globals';
2
- import <%= className %>Controller from './<%= className %>Controller.js';
2
+ import <%= className %>Controller from './<%= kebabName %>-controller.js';
3
3
 
4
4
  describe('<%= className %>Controller', () => {
5
5
  let controller;
@@ -1,15 +1,15 @@
1
1
  import { asClass, asFunction } from 'awilix';
2
2
 
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';
3
+ import <%= className %>Controller from './interfaces/controllers/<%= kebabName %>-controller.js';
4
+ import create<%= className %>Routes from './interfaces/routes/<%= kebabName %>-routes.js';
5
+ import <%= className %>UseCase from './application/usecases/<%= kebabName %>-use-case.js';
6
+ import Prisma<%= className %>Repository from './infrastructure/repositories/prisma-<%= kebabName %>-repository.js';
7
7
 
8
8
  export default function register<%= className %>Module(container) {
9
9
  container.register({
10
10
  <%= camelName %>Controller: asClass(<%= className %>Controller).singleton(),
11
11
  <%= camelName %>Routes: asFunction(create<%= className %>Routes).singleton(),
12
- Create<%= className %>UseCase: asClass(Create<%= className %>UseCase).singleton(),
13
- <%= camelName %>Repository: asFunction(({ prisma<%= className %>Repository }) => prisma<%= className %>Repository).scoped(),
12
+ <%= camelName %>UseCase: asClass(<%= className %>UseCase).singleton(),
13
+ <%= camelName %>Repository: asClass(Prisma<%= className %>Repository).singleton(),
14
14
  });
15
15
  }
@@ -1,6 +1,7 @@
1
1
  // routes
2
+ import express from 'express';
3
+
2
4
  export default ({ <%= camelName %>Controller }) => {
3
- const express = require('express');
4
5
  const router = express.Router();
5
6
 
6
7
  router.get('/', <%= camelName %>Controller.index.bind(<%= camelName %>Controller));
@@ -1,5 +1,5 @@
1
1
  import { jest, describe, it, expect, beforeEach } from '@jest/globals';
2
- import <%= className %>UseCase from './<%= className %>UseCase.js';
2
+ import <%= className %>UseCase from './<%= kebabName %>-use-case.js';
3
3
 
4
4
  describe('<%= className %>UseCase', () => {
5
5
  let useCase;
@@ -1,10 +1,27 @@
1
- exports.pascalCase = (str) => {
2
- const words = str.match(/[a-z0-9]+/gi) || [];
3
- return words.map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
1
+ export const pascalCase = (str) => {
2
+ // Split on hyphens, underscores, or camelCase boundaries
3
+ const words =
4
+ str.replace(/([a-z])([A-Z])/g, "$1 $2").match(/[a-z0-9]+/gi) || [];
5
+ return words
6
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
7
+ .join("");
4
8
  };
5
9
 
6
- exports.camelCase = (str) => {
7
- const words = str.match(/[a-z0-9]+/gi) || [];
8
- if (!words.length) return '';
9
- return words[0].toLowerCase() + words.slice(1).map(w => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join('');
10
+ export const camelCase = (str) => {
11
+ const words =
12
+ str.replace(/([a-z])([A-Z])/g, "$1 $2").match(/[a-z0-9]+/gi) || [];
13
+ if (!words.length) return "";
14
+ return (
15
+ words[0].toLowerCase() +
16
+ words
17
+ .slice(1)
18
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())
19
+ .join("")
20
+ );
21
+ };
22
+
23
+ export const kebabCase = (str) => {
24
+ const words =
25
+ str.replace(/([a-z])([A-Z])/g, "$1 $2").match(/[a-z0-9]+/gi) || [];
26
+ return words.map((w) => w.toLowerCase()).join("-");
10
27
  };
@@ -0,0 +1,46 @@
1
+ import fs from "fs-extra";
2
+ import path from "path";
3
+ import ejs from "ejs";
4
+ import logger from "./logger.util.js";
5
+ import { fileURLToPath } from "url";
6
+
7
+ const __filename = fileURLToPath(import.meta.url);
8
+ const __dirname = path.dirname(__filename);
9
+
10
+ class FileUtil {
11
+ /**
12
+ * Ensure directories exist.
13
+ * @param {string} basePath Base directory path
14
+ * @param {string[]} dirs Array of relative directory paths
15
+ */
16
+ static ensureDirectories(basePath, dirs) {
17
+ dirs.forEach((dir) => {
18
+ const fullPath = path.join(basePath, dir);
19
+ fs.ensureDirSync(fullPath);
20
+ });
21
+ }
22
+
23
+ /**
24
+ * Render EJS template and write to an output path.
25
+ * @param {string} templatePath Template path relative to templates folder
26
+ * @param {Object} data Template data
27
+ * @param {string} outputPath Target output path relative to basePath
28
+ */
29
+ static async renderAndWrite(templatePath, data, outputPath) {
30
+ try {
31
+ const absoluteTemplatePath = path.join(
32
+ __dirname,
33
+ "../templates",
34
+ templatePath,
35
+ );
36
+ const templateContent = await ejs.renderFile(absoluteTemplatePath, data);
37
+ fs.writeFileSync(outputPath, templateContent);
38
+ logger.step(`Created ${path.basename(outputPath)}`);
39
+ } catch (error) {
40
+ logger.error(`Failed to process template: ${templatePath}`, error);
41
+ throw error;
42
+ }
43
+ }
44
+ }
45
+
46
+ export default FileUtil;
@@ -0,0 +1,30 @@
1
+ import chalk from "chalk";
2
+
3
+ export default class Logger {
4
+ static info(message) {
5
+ console.log(chalk.blue("ℹ INFO: ") + message);
6
+ }
7
+
8
+ static success(message) {
9
+ console.log(chalk.green("✔ SUCCESS: ") + message);
10
+ }
11
+
12
+ static warn(message) {
13
+ console.log(chalk.yellow("⚠ WARNING: ") + message);
14
+ }
15
+
16
+ static error(message, error = null) {
17
+ console.error(chalk.red("✖ ERROR: ") + message);
18
+ if (error) {
19
+ if (error.stack) {
20
+ console.error(chalk.red(error.stack));
21
+ } else {
22
+ console.error(chalk.red(error));
23
+ }
24
+ }
25
+ }
26
+
27
+ static step(message) {
28
+ console.log(chalk.cyan("➜ ") + message);
29
+ }
30
+ }
@@ -1,38 +0,0 @@
1
- ---
2
- name: Bug report
3
- about: Create a report to help us improve
4
- title: ''
5
- labels: ''
6
- assignees: ''
7
-
8
- ---
9
-
10
- **Describe the bug**
11
- A clear and concise description of what the bug is.
12
-
13
- **To Reproduce**
14
- Steps to reproduce the behavior:
15
- 1. Go to '...'
16
- 2. Click on '....'
17
- 3. Scroll down to '....'
18
- 4. See error
19
-
20
- **Expected behavior**
21
- A clear and concise description of what you expected to happen.
22
-
23
- **Screenshots**
24
- If applicable, add screenshots to help explain your problem.
25
-
26
- **Desktop (please complete the following information):**
27
- - OS: [e.g. iOS]
28
- - Browser [e.g. chrome, safari]
29
- - Version [e.g. 22]
30
-
31
- **Smartphone (please complete the following information):**
32
- - Device: [e.g. iPhone6]
33
- - OS: [e.g. iOS8.1]
34
- - Browser [e.g. stock browser, safari]
35
- - Version [e.g. 22]
36
-
37
- **Additional context**
38
- Add any other context about the problem here.
@@ -1,10 +0,0 @@
1
- ---
2
- name: Custom issue template
3
- about: Describe this issue template's purpose here.
4
- title: ''
5
- labels: ''
6
- assignees: ''
7
-
8
- ---
9
-
10
-
@@ -1,20 +0,0 @@
1
- ---
2
- name: Feature request
3
- about: Suggest an idea for this project
4
- title: ''
5
- labels: ''
6
- assignees: ''
7
-
8
- ---
9
-
10
- **Is your feature request related to a problem? Please describe.**
11
- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12
-
13
- **Describe the solution you'd like**
14
- A clear and concise description of what you want to happen.
15
-
16
- **Describe alternatives you've considered**
17
- A clear and concise description of any alternative solutions or features you've considered.
18
-
19
- **Additional context**
20
- Add any other context or screenshots about the feature request here.
@@ -1,28 +0,0 @@
1
- name: CI
2
- on:
3
- push:
4
- branches: ["main"]
5
- pull_request:
6
- branches: ["main"]
7
-
8
- jobs:
9
- build:
10
- runs-on: ubuntu-latest
11
- strategy:
12
- matrix:
13
- node-version: [18, 20]
14
- steps:
15
- - uses: actions/checkout@v4
16
- - name: Use Node.js ${{ matrix.node-version }}
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: ${{ matrix.node-version }}
20
- - name: Cache node modules
21
- uses: actions/cache@v4
22
- with:
23
- path: ~/.npm
24
- key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
25
- - name: Install dependencies
26
- run: npm ci
27
- - name: Run tests
28
- run: npm test
@@ -1,31 +0,0 @@
1
- name: Release
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*.*.*'
7
-
8
- jobs:
9
- publish:
10
- runs-on: ubuntu-latest
11
-
12
- steps:
13
- - name: Checkout
14
- uses: actions/checkout@v4
15
-
16
- - name: Setup Node
17
- uses: actions/setup-node@v4
18
- with:
19
- node-version: 20
20
- registry-url: 'https://registry.npmjs.org'
21
-
22
- - name: Install deps
23
- run: npm install
24
-
25
- - name: Run test
26
- run: npm test
27
-
28
- - name: Publish to npm
29
- run: npm publish --access public
30
- env:
31
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
package/DOCS_STEPS.md DELETED
@@ -1,40 +0,0 @@
1
- # Langkah-langkah Setelah Generate Modul Baru
2
-
3
- Setelah menjalankan perintah `nmg module <name>`, ikuti langkah-langkah berikut untuk mengintegrasikan modul ke dalam proyek Node.js Anda:
4
-
5
- ## 1. Registrasi di Awilix Container (`src/container.js`)
6
-
7
- Buka file `src/container.js` dan tambahkan registrasi untuk repository jika Anda ingin menggunakan alias spesifik:
8
-
9
- ```javascript
10
- import { asFunction } from 'awilix';
11
-
12
- // ... di dalam container.register({ ... })
13
- container.register({
14
- // Contoh alias: [module]Repository -> prisma[Module]Repository
15
- authRepository: asFunction(({ prismaAuthRepository }) => prismaAuthRepository).scoped(),
16
- });
17
- ```
18
-
19
- *Catatan: Secara default, generator Awilix biasanya mengauto-load file. Pastikan loader Anda dikonfigurasi untuk memuat folder `usecases`, `repositories`, `controllers`, dan `routes`.*
20
-
21
- ## 2. Registrasi Route di Express (`src/app.js`)
22
-
23
- Buka file `src/app.js` dan daftarkan router dari modul yang baru dibuat:
24
-
25
- ```javascript
26
- // ...
27
- app.use('/api/v1/auth', container.resolve('authRoutes'));
28
- // ...
29
- ```
30
-
31
- ## 3. Implementasi Detail Bisnis
32
- * **Domain**: Tentukan skema data di `domain/entities`.
33
- * **Repository Interface**: Tambahkan method yang dibutuhkan di `domain/repositories`.
34
- * **Repository Implementation**: Implementasikan query database (Prisma) di `infrastructure/repositories`.
35
- * **UseCase**: Tulis logika bisnis utama di `application/usecases`.
36
- * **Controller**: Tangani input request dan panggil UseCase di `interfaces/controllers`.
37
- * **Routes**: Definisikan endpoint HTTP di `interfaces/routes`.
38
-
39
- ---
40
- *Generated by node-module-generator*
package/release.yml DELETED
File without changes
@@ -1,15 +0,0 @@
1
- import { asClass, asFunction } from 'awilix';
2
-
3
- import AuthController from './interfaces/controllers/AuthController';
4
- import createAuthRoutes from './interfaces/routes/auth.routes';
5
- import CreateAuthUseCase from './application/usecases/CreateAuthUseCase';
6
- import PrismaAuthRepository from './infrastructure/repositories/PrismaAuthRepository';
7
-
8
- export default function registerAuthModule(container) {
9
- container.register({
10
- authController: asClass(AuthController).singleton(),
11
- authRoutes: asFunction(createAuthRoutes).singleton(),
12
- CreateAuthUseCase: asClass(CreateAuthUseCase).singleton(),
13
- authRepository: asFunction(({ prismaAuthRepository }) => prismaAuthRepository).scoped(),
14
- });
15
- }
@@ -1,10 +0,0 @@
1
- // DTO Template
2
- export default {
3
- // Define DTO validation schemas here (e.g. Joi, Zod)
4
- createSchema: {
5
- // rules
6
- },
7
- updateSchema: {
8
- // rules
9
- }
10
- };
@@ -1,12 +0,0 @@
1
- export default class AuthUseCase {
2
- constructor({ authRepository, jwtService }) {
3
- this.authRepository = authRepository;
4
- this.jwtService = jwtService;
5
- }
6
-
7
- async execute(inputData) {
8
- // Logic for AuthUseCase
9
- const result = await this.authRepository.create(inputData);
10
- return { success: true, data: result };
11
- }
12
- }
@@ -1,30 +0,0 @@
1
- import { jest, describe, it, expect, beforeEach } from '@jest/globals';
2
- import AuthUseCase from './AuthUseCase.js';
3
-
4
- describe('AuthUseCase', () => {
5
- let useCase;
6
- let mockRepository;
7
-
8
- beforeEach(() => {
9
- mockRepository = {
10
- create: jest.fn()
11
- };
12
- useCase = new AuthUseCase({
13
- authRepository: mockRepository,
14
- jwtService: {}
15
- });
16
- });
17
-
18
- describe('execute', () => {
19
- it('should call repository create and return success', async () => {
20
- const mockDto = { name: 'Test' };
21
- const mockResult = { id: 1, ...mockDto };
22
- mockRepository.create.mockResolvedValue(mockResult);
23
-
24
- const result = await useCase.execute(mockDto);
25
-
26
- expect(mockRepository.create).toHaveBeenCalledWith(mockDto);
27
- expect(result).toEqual({ success: true, data: mockResult });
28
- });
29
- });
30
- });
@@ -1,5 +0,0 @@
1
- export default class Auth {
2
- constructor(props) {
3
- Object.assign(this, props);
4
- }
5
- }
@@ -1,9 +0,0 @@
1
- export default class AuthRepository {
2
- async findById(id) {
3
- throw new Error('Method not implemented.');
4
- }
5
-
6
- async create(data) {
7
- throw new Error('Method not implemented.');
8
- }
9
- }
@@ -1,15 +0,0 @@
1
- export default class PrismaAuthRepository {
2
- constructor({ prisma }) {
3
- this.prisma = prisma;
4
- }
5
-
6
- async findById(id) {
7
- return this.prisma.auths.findUnique({
8
- where: { id },
9
- });
10
- }
11
-
12
- async create(data) {
13
- return this.prisma.auths.create({ data });
14
- }
15
- }
@@ -1,15 +0,0 @@
1
- export default class AuthController {
2
- constructor({ authRepository, authUseCase }) {
3
- this.authRepository = authRepository;
4
- this.authUseCase = authUseCase;
5
- }
6
-
7
- async index(req, res, next) {
8
- try {
9
- const result = await this.authUseCase.execute(req.body);
10
- res.json(result);
11
- } catch (error) {
12
- next(error);
13
- }
14
- }
15
- }
@@ -1,49 +0,0 @@
1
- import { jest, describe, it, expect, beforeEach } from '@jest/globals';
2
- import AuthController from './AuthController.js';
3
-
4
- describe('AuthController', () => {
5
- let controller;
6
- let mockUseCase;
7
- let mockReq;
8
- let mockRes;
9
- let mockNext;
10
-
11
- beforeEach(() => {
12
- mockUseCase = {
13
- execute: jest.fn()
14
- };
15
- controller = new AuthController({
16
- authRepository: {},
17
- authUseCase: mockUseCase
18
- });
19
- mockReq = {
20
- body: { test: 'data' }
21
- };
22
- mockRes = {
23
- status: jest.fn().mockReturnThis(),
24
- json: jest.fn()
25
- };
26
- mockNext = jest.fn();
27
- });
28
-
29
- describe('index', () => {
30
- it('should return result if use case succeeds', async () => {
31
- const mockResult = { success: true, data: mockReq.body };
32
- mockUseCase.execute.mockResolvedValue(mockResult);
33
-
34
- await controller.index(mockReq, mockRes, mockNext);
35
-
36
- expect(mockUseCase.execute).toHaveBeenCalledWith(mockReq.body);
37
- expect(mockRes.json).toHaveBeenCalledWith(mockResult);
38
- });
39
-
40
- it('should call next with error if use case fails', async () => {
41
- const error = new Error('Test error');
42
- mockUseCase.execute.mockRejectedValue(error);
43
-
44
- await controller.index(mockReq, mockRes, mockNext);
45
-
46
- expect(mockNext).toHaveBeenCalledWith(error);
47
- });
48
- });
49
- });
@@ -1,9 +0,0 @@
1
- // routes
2
- export default ({ authController }) => {
3
- const express = require('express');
4
- const router = express.Router();
5
-
6
- router.get('/', authController.index.bind(authController));
7
-
8
- return router;
9
- };
@@ -1,3 +0,0 @@
1
- {
2
- "type": "module"
3
- }
@@ -1,15 +0,0 @@
1
- class CreateOrderUseCase {
2
- constructor({ orderRepository }) {
3
- this.orderRepository = orderRepository;
4
- }
5
-
6
- async execute(dto) {
7
- // Validate DTO...
8
- // Apply business logic...
9
-
10
- const entity = await this.orderRepository.save(dto);
11
- return entity;
12
- }
13
- }
14
-
15
- module.exports = CreateOrderUseCase;
@@ -1,26 +0,0 @@
1
- const CreateOrderUseCase = require('./create-order.usecase');
2
-
3
- describe('CreateOrderUseCase', () => {
4
- let useCase;
5
- let mockRepository;
6
-
7
- beforeEach(() => {
8
- mockRepository = {
9
- save: jest.fn()
10
- };
11
- useCase = new CreateOrderUseCase({ orderRepository: mockRepository });
12
- });
13
-
14
- describe('execute', () => {
15
- it('should save data using the repository and return the entity', async () => {
16
- const mockDto = { name: 'Test' };
17
- const mockEntity = { id: 1, ...mockDto };
18
- mockRepository.save.mockResolvedValue(mockEntity);
19
-
20
- const result = await useCase.execute(mockDto);
21
-
22
- expect(mockRepository.save).toHaveBeenCalledWith(mockDto);
23
- expect(result).toEqual(mockEntity);
24
- });
25
- });
26
- });
@@ -1,8 +0,0 @@
1
- class OrderEntity {
2
- constructor({ id, ...props }) {
3
- this.id = id;
4
- Object.assign(this, props);
5
- }
6
- }
7
-
8
- module.exports = OrderEntity;
@@ -1,11 +0,0 @@
1
- class IOrderRepository {
2
- async save(entity) {
3
- throw new Error('Method not implemented.');
4
- }
5
-
6
- async findById(id) {
7
- throw new Error('Method not implemented.');
8
- }
9
- }
10
-
11
- module.exports = IOrderRepository;
@@ -1,23 +0,0 @@
1
- const IOrderRepository = require('../../domain/repositories/order.repository.interface');
2
- const OrderEntity = require('../../domain/entities/order.entity');
3
-
4
- class OrderRepositoryImpl extends IOrderRepository {
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 OrderEntity({ id, ...dto });
14
- this.db.set(id, entity);
15
- return entity;
16
- }
17
-
18
- async findById(id) {
19
- return this.db.get(id) || null;
20
- }
21
- }
22
-
23
- module.exports = OrderRepositoryImpl;
@@ -1,7 +0,0 @@
1
- const Joi = require('joi'); // Usually you'd use joi or another lib
2
-
3
- const createOrderSchema = Joi.object({
4
- // Define DTO validation rules
5
- });
6
-
7
- module.exports = createOrderSchema;