nodejs-quickstart-structure 1.19.0 → 1.19.1
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/CHANGELOG.md +309 -301
- package/LICENSE +15 -15
- package/lib/generator.js +139 -139
- package/lib/modules/app-setup.js +401 -401
- package/lib/modules/config-files.js +151 -151
- package/lib/modules/database-setup.js +116 -116
- package/lib/modules/project-setup.js +32 -32
- package/lib/prompts.js +100 -100
- package/package.json +78 -78
- package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
- package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
- package/templates/clean-architecture/js/src/index.js.ejs +55 -55
- package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
- package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
- package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
- package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
- package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
- package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
- package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
- package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
- package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
- package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
- package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
- package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
- package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
- package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
- package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
- package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
- package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
- package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
- package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
- package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
- package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
- package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
- package/templates/common/.cursorrules.ejs +60 -60
- package/templates/common/.dockerignore +12 -12
- package/templates/common/.env.example.ejs +41 -41
- package/templates/common/.gitlab-ci.yml.ejs +86 -86
- package/templates/common/.lintstagedrc +6 -6
- package/templates/common/.prettierrc +7 -7
- package/templates/common/Dockerfile +73 -73
- package/templates/common/Jenkinsfile.ejs +87 -87
- package/templates/common/SECURITY.md +20 -20
- package/templates/common/_github/workflows/ci.yml.ejs +46 -46
- package/templates/common/_github/workflows/security.yml.ejs +36 -36
- package/templates/common/_gitignore +5 -5
- package/templates/common/_husky/pre-commit +4 -4
- package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
- package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
- package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
- package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
- package/templates/common/caching/js/memoryCache.js.ejs +60 -60
- package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
- package/templates/common/caching/js/redisClient.js.ejs +75 -75
- package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
- package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
- package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
- package/templates/common/database/js/database.js.ejs +19 -19
- package/templates/common/database/js/database.spec.js.ejs +56 -56
- package/templates/common/database/js/mongoose.js.ejs +33 -33
- package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
- package/templates/common/database/ts/database.spec.ts.ejs +56 -56
- package/templates/common/database/ts/database.ts.ejs +21 -21
- package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
- package/templates/common/database/ts/mongoose.ts.ejs +28 -28
- package/templates/common/docker-compose.yml.ejs +159 -159
- package/templates/common/ecosystem.config.js.ejs +40 -40
- package/templates/common/eslint.config.mjs.ejs +77 -77
- package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
- package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
- package/templates/common/jest.config.js.ejs +32 -32
- package/templates/common/kafka/js/config/kafka.js +9 -9
- package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
- package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
- package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
- package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
- package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
- package/templates/common/kafka/ts/config/kafka.ts +7 -7
- package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
- package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
- package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
- package/templates/common/migrate-mongo-config.js.ejs +31 -31
- package/templates/common/migrations/init.js.ejs +23 -23
- package/templates/common/package.json.ejs +119 -118
- package/templates/common/prompts/add-feature.md.ejs +26 -26
- package/templates/common/prompts/project-context.md.ejs +43 -43
- package/templates/common/prompts/troubleshoot.md.ejs +28 -28
- package/templates/common/public/css/style.css +147 -147
- package/templates/common/scripts/run-e2e.js.ejs +63 -63
- package/templates/common/sonar-project.properties.ejs +27 -27
- package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
- package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
- package/templates/common/tsconfig.json +22 -22
- package/templates/common/views/ejs/index.ejs +55 -55
- package/templates/common/views/pug/index.pug +40 -40
- package/templates/mvc/js/src/config/env.js.ejs +46 -46
- package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
- package/templates/mvc/js/src/errors/ApiError.js +14 -14
- package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
- package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
- package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
- package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
- package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
- package/templates/mvc/js/src/index.js.ejs +136 -136
- package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
- package/templates/mvc/js/src/utils/httpCodes.js +9 -9
- package/templates/mvc/js/src/utils/logger.js +40 -40
- package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
- package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
- package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
- package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
- package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
- package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
- package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
- package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
- package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
- package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
- package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
- package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
- package/templates/mvc/ts/src/utils/logger.ts +36 -36
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
const request = require('supertest');
|
|
2
|
-
const express = require('express');
|
|
3
|
-
const router = require('@/interfaces/routes/api');
|
|
4
|
-
|
|
5
|
-
const mockGetUsers = jest.fn().mockImplementation((req, res) => res.status(200).json([{ id: '1', name: 'John Doe' }]));
|
|
6
|
-
const mockCreateUser = jest.fn().mockImplementation((req, res) => res.status(201).json({ id: '1', name: 'Test' }));
|
|
7
|
-
|
|
8
|
-
jest.mock('@/interfaces/controllers/userController', () => {
|
|
9
|
-
return jest.fn().mockImplementation(() => ({
|
|
10
|
-
getUsers: (...args) => mockGetUsers(...args),
|
|
11
|
-
createUser: (...args) => mockCreateUser(...args)
|
|
12
|
-
}));
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
describe('ApiRoutes', () => {
|
|
16
|
-
let app;
|
|
17
|
-
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
app = express();
|
|
20
|
-
app.use(express.json());
|
|
21
|
-
app.use('/api', router);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('POST /api/users should call controller.createUser', async () => {
|
|
25
|
-
await request(app)
|
|
26
|
-
.post('/api/users')
|
|
27
|
-
.send({ name: 'Test', email: 'test@example.com' });
|
|
28
|
-
|
|
29
|
-
expect(mockCreateUser).toHaveBeenCalledTimes(1);
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it('GET /api/users should call controller.getUsers', async () => {
|
|
33
|
-
await request(app)
|
|
34
|
-
.get('/api/users');
|
|
35
|
-
|
|
36
|
-
expect(mockGetUsers).toHaveBeenCalledTimes(1);
|
|
37
|
-
});
|
|
38
|
-
});
|
|
1
|
+
const request = require('supertest');
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const router = require('@/interfaces/routes/api');
|
|
4
|
+
|
|
5
|
+
const mockGetUsers = jest.fn().mockImplementation((req, res) => res.status(200).json([{ id: '1', name: 'John Doe' }]));
|
|
6
|
+
const mockCreateUser = jest.fn().mockImplementation((req, res) => res.status(201).json({ id: '1', name: 'Test' }));
|
|
7
|
+
|
|
8
|
+
jest.mock('@/interfaces/controllers/userController', () => {
|
|
9
|
+
return jest.fn().mockImplementation(() => ({
|
|
10
|
+
getUsers: (...args) => mockGetUsers(...args),
|
|
11
|
+
createUser: (...args) => mockCreateUser(...args)
|
|
12
|
+
}));
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
describe('ApiRoutes', () => {
|
|
16
|
+
let app;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
app = express();
|
|
20
|
+
app.use(express.json());
|
|
21
|
+
app.use('/api', router);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('POST /api/users should call controller.createUser', async () => {
|
|
25
|
+
await request(app)
|
|
26
|
+
.post('/api/users')
|
|
27
|
+
.send({ name: 'Test', email: 'test@example.com' });
|
|
28
|
+
|
|
29
|
+
expect(mockCreateUser).toHaveBeenCalledTimes(1);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('GET /api/users should call controller.getUsers', async () => {
|
|
33
|
+
await request(app)
|
|
34
|
+
.get('/api/users');
|
|
35
|
+
|
|
36
|
+
expect(mockGetUsers).toHaveBeenCalledTimes(1);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
const User = require('../domain/models/User');
|
|
2
|
-
|
|
3
|
-
class CreateUser {
|
|
4
|
-
constructor(userRepository) {
|
|
5
|
-
this.userRepository = userRepository;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async execute(name, email) {
|
|
9
|
-
const user = new User(null, name, email);
|
|
10
|
-
return await this.userRepository.save(user);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
module.exports = CreateUser;
|
|
1
|
+
const User = require('../domain/models/User');
|
|
2
|
+
|
|
3
|
+
class CreateUser {
|
|
4
|
+
constructor(userRepository) {
|
|
5
|
+
this.userRepository = userRepository;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
async execute(name, email) {
|
|
9
|
+
const user = new User(null, name, email);
|
|
10
|
+
return await this.userRepository.save(user);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = CreateUser;
|
|
@@ -1,51 +1,51 @@
|
|
|
1
|
-
const CreateUser = require('@/usecases/CreateUser');
|
|
2
|
-
const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
3
|
-
<%_ if (caching !== 'None') { -%>
|
|
4
|
-
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
|
-
<%_ } -%>
|
|
6
|
-
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository');
|
|
8
|
-
<%_ if (caching !== 'None') { -%>
|
|
9
|
-
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
|
-
get: jest.fn(),
|
|
11
|
-
set: jest.fn(),
|
|
12
|
-
del: jest.fn()
|
|
13
|
-
}));
|
|
14
|
-
<%_ } -%>
|
|
15
|
-
|
|
16
|
-
describe('CreateUser UseCase', () => {
|
|
17
|
-
let createUser;
|
|
18
|
-
let mockUserRepository;
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
mockUserRepository = new UserRepository();
|
|
22
|
-
createUser = new CreateUser(mockUserRepository);
|
|
23
|
-
jest.clearAllMocks();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should create and save a new user', async () => {
|
|
27
|
-
const name = 'Test User';
|
|
28
|
-
const email = 'test@example.com';
|
|
29
|
-
const expectedResult = { id: 1, name, email };
|
|
30
|
-
|
|
31
|
-
mockUserRepository.save.mockResolvedValue(expectedResult);
|
|
32
|
-
|
|
33
|
-
const result = await createUser.execute(name, email);
|
|
34
|
-
|
|
35
|
-
expect(mockUserRepository.save).toHaveBeenCalledTimes(1);
|
|
36
|
-
const savedUser = mockUserRepository.save.mock.calls[0][0];
|
|
37
|
-
expect(savedUser.name).toBe(name);
|
|
38
|
-
expect(savedUser.email).toBe(email);
|
|
39
|
-
expect(result).toEqual(expectedResult);
|
|
40
|
-
<%_ if (caching !== 'None') { -%>
|
|
41
|
-
expect(cacheService.del).toHaveBeenCalledWith('users:all');
|
|
42
|
-
<%_ } -%>
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
it('should throw an error if repository fails', async () => {
|
|
46
|
-
const error = new Error('Database error');
|
|
47
|
-
mockUserRepository.save.mockRejectedValue(error);
|
|
48
|
-
|
|
49
|
-
await expect(createUser.execute('Test', 'test@test.com')).rejects.toThrow(error);
|
|
50
|
-
});
|
|
51
|
-
});
|
|
1
|
+
const CreateUser = require('@/usecases/CreateUser');
|
|
2
|
+
const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
3
|
+
<%_ if (caching !== 'None') { -%>
|
|
4
|
+
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
|
+
<%_ } -%>
|
|
6
|
+
|
|
7
|
+
jest.mock('@/infrastructure/repositories/UserRepository');
|
|
8
|
+
<%_ if (caching !== 'None') { -%>
|
|
9
|
+
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
|
+
get: jest.fn(),
|
|
11
|
+
set: jest.fn(),
|
|
12
|
+
del: jest.fn()
|
|
13
|
+
}));
|
|
14
|
+
<%_ } -%>
|
|
15
|
+
|
|
16
|
+
describe('CreateUser UseCase', () => {
|
|
17
|
+
let createUser;
|
|
18
|
+
let mockUserRepository;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
mockUserRepository = new UserRepository();
|
|
22
|
+
createUser = new CreateUser(mockUserRepository);
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should create and save a new user', async () => {
|
|
27
|
+
const name = 'Test User';
|
|
28
|
+
const email = 'test@example.com';
|
|
29
|
+
const expectedResult = { id: 1, name, email };
|
|
30
|
+
|
|
31
|
+
mockUserRepository.save.mockResolvedValue(expectedResult);
|
|
32
|
+
|
|
33
|
+
const result = await createUser.execute(name, email);
|
|
34
|
+
|
|
35
|
+
expect(mockUserRepository.save).toHaveBeenCalledTimes(1);
|
|
36
|
+
const savedUser = mockUserRepository.save.mock.calls[0][0];
|
|
37
|
+
expect(savedUser.name).toBe(name);
|
|
38
|
+
expect(savedUser.email).toBe(email);
|
|
39
|
+
expect(result).toEqual(expectedResult);
|
|
40
|
+
<%_ if (caching !== 'None') { -%>
|
|
41
|
+
expect(cacheService.del).toHaveBeenCalledWith('users:all');
|
|
42
|
+
<%_ } -%>
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should throw an error if repository fails', async () => {
|
|
46
|
+
const error = new Error('Database error');
|
|
47
|
+
mockUserRepository.save.mockRejectedValue(error);
|
|
48
|
+
|
|
49
|
+
await expect(createUser.execute('Test', 'test@test.com')).rejects.toThrow(error);
|
|
50
|
+
});
|
|
51
|
+
});
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
class GetAllUsers {
|
|
3
|
-
constructor(userRepository) {
|
|
4
|
-
this.userRepository = userRepository;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
async execute() {
|
|
8
|
-
return await this.userRepository.getUsers();
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
module.exports = GetAllUsers;
|
|
1
|
+
|
|
2
|
+
class GetAllUsers {
|
|
3
|
+
constructor(userRepository) {
|
|
4
|
+
this.userRepository = userRepository;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
async execute() {
|
|
8
|
+
return await this.userRepository.getUsers();
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
module.exports = GetAllUsers;
|
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
const GetAllUsers = require('@/usecases/GetAllUsers');
|
|
2
|
-
const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
3
|
-
<%_ if (caching !== 'None') { -%>
|
|
4
|
-
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
|
-
<%_ } -%>
|
|
6
|
-
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository');
|
|
8
|
-
<%_ if (caching !== 'None') { -%>
|
|
9
|
-
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
|
-
get: jest.fn(),
|
|
11
|
-
set: jest.fn(),
|
|
12
|
-
del: jest.fn()
|
|
13
|
-
}));
|
|
14
|
-
<%_ } -%>
|
|
15
|
-
|
|
16
|
-
describe('GetAllUsers UseCase', () => {
|
|
17
|
-
let getAllUsers;
|
|
18
|
-
let mockUserRepository;
|
|
19
|
-
|
|
20
|
-
beforeEach(() => {
|
|
21
|
-
mockUserRepository = new UserRepository();
|
|
22
|
-
getAllUsers = new GetAllUsers(mockUserRepository);
|
|
23
|
-
jest.clearAllMocks();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
it('should retrieve all users', async () => {
|
|
27
|
-
const expectedUsers = [{ id: 1, name: 'Alice', email: 'alice@example.com' }];
|
|
28
|
-
mockUserRepository.getUsers.mockResolvedValue(expectedUsers);
|
|
29
|
-
<%_ if (caching !== 'None') { -%>
|
|
30
|
-
cacheService.get.mockResolvedValue(null); // Cache miss
|
|
31
|
-
<%_ } -%>
|
|
32
|
-
const result = await getAllUsers.execute();
|
|
33
|
-
|
|
34
|
-
expect(mockUserRepository.getUsers).toHaveBeenCalledTimes(1);
|
|
35
|
-
expect(result).toEqual(expectedUsers);
|
|
36
|
-
<%_ if (caching !== 'None') { -%>
|
|
37
|
-
expect(cacheService.set).toHaveBeenCalled();
|
|
38
|
-
<%_ } -%>
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
<%_ if (caching !== 'None') { -%>
|
|
42
|
-
it('should return from cache if available', async () => {
|
|
43
|
-
const cachedUsers = [{ id: 1, name: 'Cached', email: 'cached@example.com' }];
|
|
44
|
-
cacheService.get.mockResolvedValue(cachedUsers);
|
|
45
|
-
|
|
46
|
-
const result = await getAllUsers.execute();
|
|
47
|
-
|
|
48
|
-
expect(mockUserRepository.getUsers).not.toHaveBeenCalled();
|
|
49
|
-
expect(result).toEqual(cachedUsers);
|
|
50
|
-
});
|
|
51
|
-
<%_ } -%>
|
|
52
|
-
|
|
53
|
-
it('should throw an error if repository fails', async () => {
|
|
54
|
-
const error = new Error('Database error');
|
|
55
|
-
mockUserRepository.getUsers.mockRejectedValue(error);
|
|
56
|
-
<%_ if (caching !== 'None') { -%>
|
|
57
|
-
cacheService.get.mockResolvedValue(null); // Cache miss
|
|
58
|
-
<%_ } -%>
|
|
59
|
-
await expect(getAllUsers.execute()).rejects.toThrow(error);
|
|
60
|
-
});
|
|
61
|
-
});
|
|
1
|
+
const GetAllUsers = require('@/usecases/GetAllUsers');
|
|
2
|
+
const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
3
|
+
<%_ if (caching !== 'None') { -%>
|
|
4
|
+
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
|
+
<%_ } -%>
|
|
6
|
+
|
|
7
|
+
jest.mock('@/infrastructure/repositories/UserRepository');
|
|
8
|
+
<%_ if (caching !== 'None') { -%>
|
|
9
|
+
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
|
+
get: jest.fn(),
|
|
11
|
+
set: jest.fn(),
|
|
12
|
+
del: jest.fn()
|
|
13
|
+
}));
|
|
14
|
+
<%_ } -%>
|
|
15
|
+
|
|
16
|
+
describe('GetAllUsers UseCase', () => {
|
|
17
|
+
let getAllUsers;
|
|
18
|
+
let mockUserRepository;
|
|
19
|
+
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
mockUserRepository = new UserRepository();
|
|
22
|
+
getAllUsers = new GetAllUsers(mockUserRepository);
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
it('should retrieve all users', async () => {
|
|
27
|
+
const expectedUsers = [{ id: 1, name: 'Alice', email: 'alice@example.com' }];
|
|
28
|
+
mockUserRepository.getUsers.mockResolvedValue(expectedUsers);
|
|
29
|
+
<%_ if (caching !== 'None') { -%>
|
|
30
|
+
cacheService.get.mockResolvedValue(null); // Cache miss
|
|
31
|
+
<%_ } -%>
|
|
32
|
+
const result = await getAllUsers.execute();
|
|
33
|
+
|
|
34
|
+
expect(mockUserRepository.getUsers).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(result).toEqual(expectedUsers);
|
|
36
|
+
<%_ if (caching !== 'None') { -%>
|
|
37
|
+
expect(cacheService.set).toHaveBeenCalled();
|
|
38
|
+
<%_ } -%>
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
<%_ if (caching !== 'None') { -%>
|
|
42
|
+
it('should return from cache if available', async () => {
|
|
43
|
+
const cachedUsers = [{ id: 1, name: 'Cached', email: 'cached@example.com' }];
|
|
44
|
+
cacheService.get.mockResolvedValue(cachedUsers);
|
|
45
|
+
|
|
46
|
+
const result = await getAllUsers.execute();
|
|
47
|
+
|
|
48
|
+
expect(mockUserRepository.getUsers).not.toHaveBeenCalled();
|
|
49
|
+
expect(result).toEqual(cachedUsers);
|
|
50
|
+
});
|
|
51
|
+
<%_ } -%>
|
|
52
|
+
|
|
53
|
+
it('should throw an error if repository fails', async () => {
|
|
54
|
+
const error = new Error('Database error');
|
|
55
|
+
mockUserRepository.getUsers.mockRejectedValue(error);
|
|
56
|
+
<%_ if (caching !== 'None') { -%>
|
|
57
|
+
cacheService.get.mockResolvedValue(null); // Cache miss
|
|
58
|
+
<%_ } -%>
|
|
59
|
+
await expect(getAllUsers.execute()).rejects.toThrow(error);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const HTTP_STATUS = {
|
|
2
|
-
OK: 200,
|
|
3
|
-
CREATED: 201,
|
|
4
|
-
BAD_REQUEST: 400,
|
|
5
|
-
NOT_FOUND: 404,
|
|
6
|
-
INTERNAL_SERVER_ERROR: 500
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
module.exports = HTTP_STATUS;
|
|
1
|
+
const HTTP_STATUS = {
|
|
2
|
+
OK: 200,
|
|
3
|
+
CREATED: 201,
|
|
4
|
+
BAD_REQUEST: 400,
|
|
5
|
+
NOT_FOUND: 404,
|
|
6
|
+
INTERNAL_SERVER_ERROR: 500
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
module.exports = HTTP_STATUS;
|
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import dotenv from 'dotenv';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import logger from '@/infrastructure/log/logger';
|
|
4
|
-
|
|
5
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
6
|
-
dotenv.config();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
const envSchema = z.object({
|
|
10
|
-
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
11
|
-
PORT: z.string().transform(Number).default('3000'),
|
|
12
|
-
<%_ if (database !== 'None') { -%>
|
|
13
|
-
DB_HOST: z.string(),
|
|
14
|
-
<%_ if (database === 'MySQL') { -%>
|
|
15
|
-
DB_USER: z.string(),
|
|
16
|
-
DB_PASSWORD: z.string(),
|
|
17
|
-
DB_NAME: z.string(),
|
|
18
|
-
DB_PORT: z.string().transform(Number),
|
|
19
|
-
<%_ } else if (database === 'PostgreSQL') { -%>
|
|
20
|
-
DB_USER: z.string(),
|
|
21
|
-
DB_PASSWORD: z.string(),
|
|
22
|
-
DB_NAME: z.string(),
|
|
23
|
-
DB_PORT: z.string().transform(Number),
|
|
24
|
-
<%_ } else if (database === 'MongoDB') { -%>
|
|
25
|
-
DB_NAME: z.string(),
|
|
26
|
-
DB_PORT: z.string().transform(Number),
|
|
27
|
-
<%_ } -%>
|
|
28
|
-
<%_ } -%>
|
|
29
|
-
<%_ if (caching === 'Redis') { -%>
|
|
30
|
-
REDIS_HOST: z.string(),
|
|
31
|
-
REDIS_PORT: z.string().transform(Number),
|
|
32
|
-
REDIS_PASSWORD: z.string().optional(),
|
|
33
|
-
<%_ } -%>
|
|
34
|
-
<%_ if (communication === 'Kafka') { -%>
|
|
35
|
-
KAFKA_BROKER: z.string(),
|
|
36
|
-
<%_ } -%>
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
const _env = envSchema.safeParse(process.env);
|
|
40
|
-
|
|
41
|
-
if (!_env.success) {
|
|
42
|
-
logger.error('❌ Invalid environment variables:', _env.error.format());
|
|
43
|
-
process.exit(1);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export const env = _env.data;
|
|
1
|
+
import dotenv from 'dotenv';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import logger from '@/infrastructure/log/logger';
|
|
4
|
+
|
|
5
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
6
|
+
dotenv.config();
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const envSchema = z.object({
|
|
10
|
+
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
11
|
+
PORT: z.string().transform(Number).default('3000'),
|
|
12
|
+
<%_ if (database !== 'None') { -%>
|
|
13
|
+
DB_HOST: z.string(),
|
|
14
|
+
<%_ if (database === 'MySQL') { -%>
|
|
15
|
+
DB_USER: z.string(),
|
|
16
|
+
DB_PASSWORD: z.string(),
|
|
17
|
+
DB_NAME: z.string(),
|
|
18
|
+
DB_PORT: z.string().transform(Number),
|
|
19
|
+
<%_ } else if (database === 'PostgreSQL') { -%>
|
|
20
|
+
DB_USER: z.string(),
|
|
21
|
+
DB_PASSWORD: z.string(),
|
|
22
|
+
DB_NAME: z.string(),
|
|
23
|
+
DB_PORT: z.string().transform(Number),
|
|
24
|
+
<%_ } else if (database === 'MongoDB') { -%>
|
|
25
|
+
DB_NAME: z.string(),
|
|
26
|
+
DB_PORT: z.string().transform(Number),
|
|
27
|
+
<%_ } -%>
|
|
28
|
+
<%_ } -%>
|
|
29
|
+
<%_ if (caching === 'Redis') { -%>
|
|
30
|
+
REDIS_HOST: z.string(),
|
|
31
|
+
REDIS_PORT: z.string().transform(Number),
|
|
32
|
+
REDIS_PASSWORD: z.string().optional(),
|
|
33
|
+
<%_ } -%>
|
|
34
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
35
|
+
KAFKA_BROKER: z.string(),
|
|
36
|
+
<%_ } -%>
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const _env = envSchema.safeParse(process.env);
|
|
40
|
+
|
|
41
|
+
if (!_env.success) {
|
|
42
|
+
logger.error('❌ Invalid environment variables:', _env.error.format());
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const env = _env.data;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
<% if (communication === 'REST APIs' || communication === 'Kafka') { %>import path from 'path';
|
|
2
|
-
import YAML from 'yamljs';
|
|
3
|
-
|
|
4
|
-
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
5
|
-
|
|
6
|
-
export default swaggerDocument;<% } %>
|
|
1
|
+
<% if (communication === 'REST APIs' || communication === 'Kafka') { %>import path from 'path';
|
|
2
|
+
import YAML from 'yamljs';
|
|
3
|
+
|
|
4
|
+
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
5
|
+
|
|
6
|
+
export default swaggerDocument;<% } %>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export class User {
|
|
2
|
-
constructor(
|
|
3
|
-
public id: number | string | null,
|
|
4
|
-
public name: string,
|
|
5
|
-
public email: string
|
|
6
|
-
) { }
|
|
7
|
-
}
|
|
1
|
+
export class User {
|
|
2
|
+
constructor(
|
|
3
|
+
public id: number | string | null,
|
|
4
|
+
public name: string,
|
|
5
|
+
public email: string
|
|
6
|
+
) { }
|
|
7
|
+
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
export class ApiError extends Error {
|
|
2
|
-
statusCode: number;
|
|
3
|
-
isOperational: boolean;
|
|
4
|
-
|
|
5
|
-
constructor(statusCode: number, message: string, isOperational = true, stack = '') {
|
|
6
|
-
super(message);
|
|
7
|
-
this.statusCode = statusCode;
|
|
8
|
-
this.isOperational = isOperational;
|
|
9
|
-
if (stack) {
|
|
10
|
-
this.stack = stack;
|
|
11
|
-
} else {
|
|
12
|
-
Error.captureStackTrace(this, this.constructor);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
isOperational: boolean;
|
|
4
|
+
|
|
5
|
+
constructor(statusCode: number, message: string, isOperational = true, stack = '') {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.isOperational = isOperational;
|
|
9
|
+
if (stack) {
|
|
10
|
+
this.stack = stack;
|
|
11
|
+
} else {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|