@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@saulpaulus17/node-module-generator",
|
|
3
|
-
"version": "
|
|
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": "
|
|
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": "^
|
|
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 './<%=
|
|
2
|
+
import <%= className %>Controller from './<%= kebabName %>-controller.js';
|
|
3
3
|
|
|
4
4
|
describe('<%= className %>Controller', () => {
|
|
5
5
|
let controller;
|
package/templates/module/di.ejs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { asClass, asFunction } from 'awilix';
|
|
2
2
|
|
|
3
|
-
import <%= className %>Controller from './interfaces/controllers/<%=
|
|
4
|
-
import create<%= className %>Routes from './interfaces/routes/<%=
|
|
5
|
-
import
|
|
6
|
-
import Prisma<%= className %>Repository from './infrastructure/repositories/
|
|
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
|
-
|
|
13
|
-
<%= camelName %>Repository:
|
|
12
|
+
<%= camelName %>UseCase: asClass(<%= className %>UseCase).singleton(),
|
|
13
|
+
<%= camelName %>Repository: asClass(Prisma<%= className %>Repository).singleton(),
|
|
14
14
|
});
|
|
15
15
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jest, describe, it, expect, beforeEach } from '@jest/globals';
|
|
2
|
-
import <%= className %>UseCase from './<%=
|
|
2
|
+
import <%= className %>UseCase from './<%= kebabName %>-use-case.js';
|
|
3
3
|
|
|
4
4
|
describe('<%= className %>UseCase', () => {
|
|
5
5
|
let useCase;
|
package/utils/case.util.js
CHANGED
|
@@ -1,10 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
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
|
-
|
|
7
|
-
const words =
|
|
8
|
-
|
|
9
|
-
|
|
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
|
};
|
package/utils/file.util.js
CHANGED
|
@@ -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;
|
package/utils/logger.util.js
CHANGED
|
@@ -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,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.
|
package/.github/workflows/ci.yml
DELETED
|
@@ -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,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,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,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,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;
|