nodejs-quickstart-structure 2.0.1 → 2.1.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 +25 -0
- package/README.md +64 -66
- package/bin/index.js +5 -2
- package/lib/generator.js +10 -4
- package/lib/modules/app-setup.js +76 -6
- package/lib/modules/auth-setup.js +143 -0
- package/lib/modules/caching-setup.js +8 -1
- package/lib/modules/config-files.js +6 -0
- package/lib/modules/database-setup.js +2 -1
- package/lib/modules/project-setup.js +1 -0
- package/lib/prompts.js +39 -0
- package/package.json +5 -4
- package/templates/clean-architecture/js/src/domain/models/User.js +3 -1
- package/templates/clean-architecture/js/src/index.js.ejs +2 -0
- package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +12 -3
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +25 -2
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +38 -1
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +3 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.spec.js.ejs +51 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.spec.js.ejs +14 -0
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +41 -4
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +70 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +55 -22
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +10 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +1 -1
- package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +15 -0
- package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +4 -0
- package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +34 -0
- package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +12 -3
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js.ejs +27 -0
- package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +9 -1
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js.ejs +36 -0
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +23 -1
- package/templates/clean-architecture/js/src/usecases/GetUserById.js.ejs +36 -0
- package/templates/clean-architecture/js/src/usecases/GetUserById.spec.js.ejs +48 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +28 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +9 -1
- package/templates/clean-architecture/js/src/utils/errorMessages.js +1 -0
- package/templates/clean-architecture/js/src/utils/httpCodes.js +2 -0
- package/templates/clean-architecture/ts/src/config/env.ts.ejs +12 -3
- package/templates/clean-architecture/ts/src/domain/user.ts +3 -1
- package/templates/clean-architecture/ts/src/index.ts.ejs +4 -0
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +71 -10
- package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +32 -3
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +43 -9
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +57 -15
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +57 -24
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +14 -8
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +33 -10
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +15 -5
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +1 -1
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +9 -1
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +16 -0
- package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +12 -3
- package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +35 -0
- package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +10 -1
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts.ejs +24 -0
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +9 -1
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts.ejs +21 -0
- package/templates/clean-architecture/ts/src/usecases/getUserById.spec.ts.ejs +55 -0
- package/templates/clean-architecture/ts/src/usecases/getUserById.ts.ejs +23 -0
- package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +10 -1
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +25 -0
- package/templates/clean-architecture/ts/src/utils/errorMessages.ts +1 -0
- package/templates/clean-architecture/ts/src/utils/httpCodes.ts +1 -0
- package/templates/common/.cursorrules.ejs +9 -0
- package/templates/common/.env.example.ejs +17 -10
- package/templates/common/README.md.ejs +63 -18
- package/templates/common/auth/js/controllers/authController.js.ejs +170 -0
- package/templates/common/auth/js/controllers/authController.spec.js.ejs +148 -0
- package/templates/common/auth/js/middleware/authMiddleware.js.ejs +58 -0
- package/templates/common/auth/js/middleware/authMiddleware.spec.js.ejs +108 -0
- package/templates/common/auth/js/routes/authRoutes.js.ejs +16 -0
- package/templates/common/auth/js/services/jwtService.js.ejs +54 -0
- package/templates/common/auth/js/services/jwtService.spec.js.ejs +84 -0
- package/templates/common/auth/ts/controllers/authController.spec.ts.ejs +161 -0
- package/templates/common/auth/ts/controllers/authController.ts.ejs +167 -0
- package/templates/common/auth/ts/middleware/authMiddleware.spec.ts.ejs +128 -0
- package/templates/common/auth/ts/middleware/authMiddleware.ts.ejs +59 -0
- package/templates/common/auth/ts/routes/authRoutes.ts.ejs +20 -0
- package/templates/common/auth/ts/services/jwtService.spec.ts.ejs +89 -0
- package/templates/common/auth/ts/services/jwtService.ts.ejs +60 -0
- package/templates/common/babel.config.js.ejs +5 -0
- package/templates/common/caching/clean/js/CreateUser.js.ejs +14 -5
- package/templates/common/caching/clean/js/DeleteUser.js.ejs +2 -1
- package/templates/common/caching/clean/js/GetUserById.js.ejs +39 -0
- package/templates/common/caching/clean/js/UpdateUser.js.ejs +2 -1
- package/templates/common/caching/clean/ts/createUser.ts.ejs +14 -6
- package/templates/common/caching/clean/ts/deleteUser.ts.ejs +2 -1
- package/templates/common/caching/clean/ts/getUserById.ts.ejs +32 -0
- package/templates/common/caching/clean/ts/updateUser.ts.ejs +2 -1
- package/templates/common/caching/js/memoryCache.spec.js.ejs +2 -0
- package/templates/common/caching/js/redisClient.spec.js.ejs +2 -0
- package/templates/common/caching/ts/memoryCache.spec.ts.ejs +2 -0
- package/templates/common/caching/ts/redisClient.spec.ts.ejs +2 -0
- package/templates/common/database/js/models/User.js.ejs +14 -1
- package/templates/common/database/js/models/User.js.mongoose.ejs +7 -0
- package/templates/common/database/js/models/User.spec.js.ejs +12 -0
- package/templates/common/database/js/mongoose.spec.js.ejs +2 -0
- package/templates/common/database/ts/models/User.spec.ts.ejs +10 -0
- package/templates/common/database/ts/models/User.ts.ejs +17 -0
- package/templates/common/database/ts/models/User.ts.mongoose.ejs +8 -0
- package/templates/common/database/ts/mongoose.spec.ts.ejs +2 -0
- package/templates/common/docker-compose.yml.ejs +12 -0
- package/templates/common/ecosystem.config.js.ejs +9 -3
- package/templates/common/eslint.config.mjs.ejs +3 -0
- package/templates/common/jest.config.js.ejs +13 -9
- package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +1 -1
- package/templates/common/kafka/js/services/kafkaService.js.ejs +1 -1
- package/templates/common/migrations/init.js.ejs +5 -4
- package/templates/common/package.json.ejs +11 -2
- package/templates/common/prompts/project-context.md.ejs +8 -1
- package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +149 -107
- package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +88 -47
- package/templates/common/swagger.yml.ejs +148 -0
- package/templates/common/tsconfig.eslint.json +15 -0
- package/templates/common/tsconfig.json +3 -1
- package/templates/common/views/ejs/index.ejs +264 -30
- package/templates/common/views/ejs/login.ejs.ejs +244 -0
- package/templates/common/views/ejs/signup.ejs.ejs +282 -0
- package/templates/common/views/pug/index.pug +269 -38
- package/templates/common/views/pug/login.pug.ejs +195 -0
- package/templates/common/views/pug/signup.pug.ejs +241 -0
- package/templates/db/mysql/V1__Initial_Setup.sql.ejs +6 -0
- package/templates/db/postgres/V1__Initial_Setup.sql.ejs +6 -0
- package/templates/mvc/js/src/config/env.js.ejs +12 -3
- package/templates/mvc/js/src/controllers/userController.js.ejs +29 -5
- package/templates/mvc/js/src/controllers/userController.spec.js.ejs +27 -12
- package/templates/mvc/js/src/graphql/context.js.ejs +14 -3
- package/templates/mvc/js/src/graphql/context.spec.js.ejs +36 -21
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +10 -5
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +1 -1
- package/templates/mvc/js/src/index.js.ejs +16 -3
- package/templates/mvc/js/src/routes/api.js.ejs +14 -0
- package/templates/mvc/js/src/routes/api.spec.js.ejs +3 -0
- package/templates/mvc/js/src/utils/errorMessages.js +1 -0
- package/templates/mvc/js/src/utils/httpCodes.js +1 -0
- package/templates/mvc/ts/src/config/env.ts.ejs +12 -3
- package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +95 -7
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +68 -11
- package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +36 -23
- package/templates/mvc/ts/src/graphql/context.ts.ejs +15 -6
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +32 -10
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +15 -5
- package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +1 -1
- package/templates/mvc/ts/src/index.ts.ejs +15 -3
- package/templates/mvc/ts/src/routes/api.spec.ts.ejs +6 -0
- package/templates/mvc/ts/src/routes/api.ts.ejs +15 -0
- package/templates/mvc/ts/src/utils/errorMessages.ts +1 -0
- package/templates/mvc/ts/src/utils/httpCodes.ts +1 -0
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +0 -12
- package/templates/clean-architecture/js/src/usecases/CreateUser.js +0 -14
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js +0 -11
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +0 -12
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js +0 -11
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +0 -13
- package/templates/clean-architecture/ts/src/usecases/createUser.ts +0 -13
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +0 -9
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +0 -10
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts +0 -9
- package/templates/mvc/js/src/routes/api.js +0 -10
- package/templates/mvc/ts/src/routes/api.ts +0 -12
|
@@ -1,31 +1,64 @@
|
|
|
1
|
+
<% if (auth.includes('JWT')) { %>
|
|
2
|
+
const JwtService = require('@/infrastructure/auth/jwtService');
|
|
3
|
+
jest.mock('@/infrastructure/auth/jwtService', () => ({
|
|
4
|
+
verifyToken: jest.fn(),
|
|
5
|
+
generateToken: jest.fn(),
|
|
6
|
+
generateRefreshToken: jest.fn(),
|
|
7
|
+
verifyRefreshToken: jest.fn(),
|
|
8
|
+
decodeToken: jest.fn(),
|
|
9
|
+
}));
|
|
10
|
+
<% } %>
|
|
1
11
|
const { gqlContext } = require('@/interfaces/graphql/context');
|
|
2
|
-
const { resolvers } = require('@/interfaces/graphql/
|
|
3
|
-
const { typeDefs } = require('@/interfaces/graphql/typeDefs');
|
|
12
|
+
const { resolvers } = require('@/interfaces/graphql/index');
|
|
13
|
+
const { typeDefs } = require('@/interfaces/graphql/typeDefs/index');
|
|
4
14
|
|
|
5
|
-
jest.mock('@/infrastructure/repositories/UserRepository')
|
|
15
|
+
jest.mock('@/infrastructure/repositories/UserRepository', () => {
|
|
16
|
+
return jest.fn().mockImplementation(() => ({
|
|
17
|
+
save: jest.fn(),
|
|
18
|
+
findById: jest.fn(),
|
|
19
|
+
getUsers: jest.fn(),
|
|
20
|
+
update: jest.fn(),
|
|
21
|
+
delete: jest.fn()
|
|
22
|
+
}));
|
|
23
|
+
});
|
|
6
24
|
|
|
7
25
|
describe('GraphQL Context', () => {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
expect(typeDefs).toBeDefined();
|
|
26
|
+
afterEach(() => {
|
|
27
|
+
jest.clearAllMocks();
|
|
11
28
|
});
|
|
12
|
-
it('should return context with token when authorization header is present', async () => {
|
|
13
|
-
const mockRequest = {
|
|
14
|
-
headers: {
|
|
15
|
-
authorization: 'Bearer token123',
|
|
16
|
-
},
|
|
17
|
-
};
|
|
18
29
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
30
|
+
it('should return context with user when authorization header is present and valid', async () => {
|
|
31
|
+
<% if (auth.includes('JWT')) { %>
|
|
32
|
+
const mockUser = { id: '1', email: 'test@test.com' };
|
|
33
|
+
JwtService.verifyToken.mockReturnValue(mockUser);
|
|
34
|
+
const mockRequest = {
|
|
35
|
+
headers: {
|
|
36
|
+
authorization: 'Bearer valid-token',
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const context = await gqlContext({ req: mockRequest });
|
|
41
|
+
expect(context.user).toEqual(mockUser);
|
|
42
|
+
expect(JwtService.verifyToken).toHaveBeenCalledWith('valid-token');
|
|
43
|
+
<% } else { %>
|
|
44
|
+
const mockRequest = {
|
|
45
|
+
headers: {
|
|
46
|
+
authorization: 'Bearer token123',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const context = await gqlContext({ req: mockRequest });
|
|
50
|
+
expect(context.user).toBeUndefined();
|
|
51
|
+
<% } %>
|
|
52
|
+
expect(context.userRepository).toBeDefined();
|
|
53
|
+
});
|
|
22
54
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
55
|
+
it('should return context without user when authorization header is missing', async () => {
|
|
56
|
+
const mockRequest = {
|
|
57
|
+
headers: {},
|
|
58
|
+
};
|
|
27
59
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
60
|
+
const context = await gqlContext({ req: mockRequest });
|
|
61
|
+
expect(context.user).toBeUndefined();
|
|
62
|
+
expect(context.userRepository).toBeDefined();
|
|
63
|
+
});
|
|
31
64
|
});
|
package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs
CHANGED
|
@@ -4,18 +4,23 @@ const userController = new UserController();
|
|
|
4
4
|
|
|
5
5
|
const userResolvers = {
|
|
6
6
|
Query: {
|
|
7
|
-
getAllUsers: async () => {
|
|
7
|
+
getAllUsers: async (_, __, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
8
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
8
9
|
return await userController.getUsers();
|
|
9
10
|
}
|
|
10
11
|
},
|
|
11
12
|
Mutation: {
|
|
12
|
-
createUser: async (_, { name, email }) => {
|
|
13
|
-
|
|
13
|
+
createUser: async (_, { name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> }) => {
|
|
14
|
+
// Create user is typically public for registration
|
|
15
|
+
const user = await userController.createUser({ name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> });
|
|
16
|
+
return user;
|
|
14
17
|
},
|
|
15
|
-
updateUser: async (_, { id, name, email }) => {
|
|
18
|
+
updateUser: async (_, { id, name, email }, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
19
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
16
20
|
return await userController.updateUser(id, { name, email });
|
|
17
21
|
},
|
|
18
|
-
deleteUser: async (_, { id }) => {
|
|
22
|
+
deleteUser: async (_, { id }, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
23
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
19
24
|
return await userController.deleteUser(id);
|
|
20
25
|
}
|
|
21
26
|
}<%_ if (database === 'MongoDB') { -%>,
|
package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs
CHANGED
|
@@ -13,40 +13,62 @@ jest.mock('@/interfaces/controllers/userController', () => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
describe('User Resolvers', () => {
|
|
16
|
+
const mockContext = {
|
|
17
|
+
<% if (auth.includes('JWT')) { %>user: { id: 'admin', email: 'admin@test.com' }<% } %>
|
|
18
|
+
};
|
|
19
|
+
|
|
16
20
|
afterEach(() => {
|
|
17
21
|
jest.clearAllMocks();
|
|
18
22
|
});
|
|
19
23
|
|
|
20
24
|
describe('Query.getAllUsers', () => {
|
|
21
|
-
it('should return all users', async () => {
|
|
22
|
-
const result = await userResolvers.Query.getAllUsers();
|
|
25
|
+
it('should return all users when authorized', async () => {
|
|
26
|
+
const result = await userResolvers.Query.getAllUsers(null, null, mockContext);
|
|
23
27
|
expect(result).toEqual([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
|
|
24
28
|
expect(mockGetUsers).toHaveBeenCalledTimes(1);
|
|
25
29
|
});
|
|
30
|
+
|
|
31
|
+
<% if (auth.includes('JWT')) { %>
|
|
32
|
+
it('should throw error when unauthorized', async () => {
|
|
33
|
+
await expect(userResolvers.Query.getAllUsers(null, null, {})).rejects.toThrow('Unauthorized');
|
|
34
|
+
});
|
|
35
|
+
<% } %>
|
|
26
36
|
});
|
|
27
37
|
|
|
28
38
|
describe('Mutation.createUser', () => {
|
|
29
|
-
it('should create and return a new user', async () => {
|
|
30
|
-
const
|
|
39
|
+
it('should create and return a new user (Public)', async () => {
|
|
40
|
+
const payload = { name: 'Jane', email: 'jane@example.com'<% if (auth.some(a => a !=='None')) { %>, password: 'password123'<% } %> };
|
|
41
|
+
const result = await userResolvers.Mutation.createUser(null, payload);
|
|
31
42
|
expect(result).toEqual({ id: '1', name: 'Jane', email: 'jane@example.com' });
|
|
32
|
-
expect(mockCreateUser).toHaveBeenCalledWith(
|
|
33
|
-
expect(mockCreateUser).toHaveBeenCalledTimes(1);
|
|
43
|
+
expect(mockCreateUser).toHaveBeenCalledWith(payload);
|
|
34
44
|
});
|
|
35
45
|
});
|
|
36
46
|
|
|
37
47
|
describe('Mutation.updateUser', () => {
|
|
38
|
-
it('should update and return the user', async () => {
|
|
48
|
+
it('should update and return the user when authorized', async () => {
|
|
39
49
|
const payload = { name: 'Updated' };
|
|
40
|
-
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload });
|
|
50
|
+
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload }, mockContext);
|
|
41
51
|
expect(result).toMatchObject(payload);
|
|
42
52
|
});
|
|
53
|
+
|
|
54
|
+
<% if (auth.includes('JWT')) { %>
|
|
55
|
+
it('should throw error when unauthorized', async () => {
|
|
56
|
+
await expect(userResolvers.Mutation.updateUser(null, { id: '1', name: 'N' }, {})).rejects.toThrow('Unauthorized');
|
|
57
|
+
});
|
|
58
|
+
<% } %>
|
|
43
59
|
});
|
|
44
60
|
|
|
45
61
|
describe('Mutation.deleteUser', () => {
|
|
46
|
-
it('should delete and return true', async () => {
|
|
47
|
-
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' });
|
|
62
|
+
it('should delete and return true when authorized', async () => {
|
|
63
|
+
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' }, mockContext);
|
|
48
64
|
expect(result).toBe(true);
|
|
49
65
|
});
|
|
66
|
+
|
|
67
|
+
<% if (auth.includes('JWT')) { %>
|
|
68
|
+
it('should throw error when unauthorized', async () => {
|
|
69
|
+
await expect(userResolvers.Mutation.deleteUser(null, { id: '1' }, {})).rejects.toThrow('Unauthorized');
|
|
70
|
+
});
|
|
71
|
+
<% } %>
|
|
50
72
|
});
|
|
51
73
|
<%_ if (database === 'MongoDB') { -%>
|
|
52
74
|
describe('User.id', () => {
|
|
@@ -10,7 +10,7 @@ const userTypes = `#graphql
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
type Mutation {
|
|
13
|
-
createUser(name: String!, email: String
|
|
13
|
+
createUser(name: String!, email: String!<%_ if (auth.some(a => a !=='None')) { _%>, password: String!<%_ } _%>): User
|
|
14
14
|
updateUser(id: ID!, name: String, email: String): User
|
|
15
15
|
deleteUser(id: ID!): Boolean
|
|
16
16
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const UserController = require('../controllers/userController');
|
|
3
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
4
|
+
const authMiddleware = require('../../infrastructure/webserver/middleware/authMiddleware');
|
|
5
|
+
<%_ } _%>
|
|
6
|
+
const router = express.Router();
|
|
7
|
+
const userController = new UserController();
|
|
8
|
+
|
|
9
|
+
router.get('/users', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>(req, res, next) => userController.getUsers(req, res, next));
|
|
10
|
+
router.get('/users/:id', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>(req, res, next) => userController.getUserById(req, res, next));
|
|
11
|
+
router.post('/users', (req, res, next) => userController.createUser(req, res, next));
|
|
12
|
+
router.patch('/users/:id', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>(req, res, next) => userController.updateUser(req, res, next));
|
|
13
|
+
router.delete('/users/:id', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>(req, res, next) => userController.deleteUser(req, res, next));
|
|
14
|
+
|
|
15
|
+
module.exports = router;
|
|
@@ -12,6 +12,10 @@ jest.mock('@/interfaces/controllers/userController', () => {
|
|
|
12
12
|
}));
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
+
<% if (auth.includes('JWT')) { %>
|
|
16
|
+
jest.mock('@/infrastructure/webserver/middleware/authMiddleware', () => (req, res, next) => next());
|
|
17
|
+
<% } %>
|
|
18
|
+
|
|
15
19
|
describe('ApiRoutes', () => {
|
|
16
20
|
let app;
|
|
17
21
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
const User = require('../domain/models/User');
|
|
2
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
3
|
+
const bcrypt = require('bcryptjs');
|
|
4
|
+
<%_ } _%>
|
|
5
|
+
<%_ if (caching !== 'None') { _%>
|
|
6
|
+
const cacheService = require('<% if (caching === "Redis") { %>../infrastructure/caching/redisClient<% } else { %>../infrastructure/caching/memoryCache<% } %>');
|
|
7
|
+
const logger = require('../infrastructure/log/logger');
|
|
8
|
+
<%_ } _%>
|
|
9
|
+
|
|
10
|
+
class CreateUser {
|
|
11
|
+
constructor(userRepository) {
|
|
12
|
+
this.userRepository = userRepository;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async execute(name, email, password) {
|
|
16
|
+
let finalPassword = password;
|
|
17
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
18
|
+
if (password) {
|
|
19
|
+
finalPassword = await bcrypt.hash(password, 10);
|
|
20
|
+
}<%_ } -%>
|
|
21
|
+
const user = new User(null, name, email, finalPassword);
|
|
22
|
+
const savedUser = await this.userRepository.save(user);
|
|
23
|
+
<%_ if (caching !== 'None') { -%>
|
|
24
|
+
try {
|
|
25
|
+
await cacheService.del('users:all');
|
|
26
|
+
logger.info('Invalidated users:all cache');
|
|
27
|
+
} catch (error) {
|
|
28
|
+
logger.error('Cache error (del):', error);
|
|
29
|
+
}<%_ } _%>
|
|
30
|
+
return savedUser;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
module.exports = CreateUser;
|
|
@@ -4,7 +4,15 @@ const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
|
4
4
|
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
5
|
<%_ } -%>
|
|
6
6
|
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository')
|
|
7
|
+
jest.mock('@/infrastructure/repositories/UserRepository', () => {
|
|
8
|
+
return jest.fn().mockImplementation(() => ({
|
|
9
|
+
save: jest.fn(),
|
|
10
|
+
findById: jest.fn(),
|
|
11
|
+
getUsers: jest.fn(),
|
|
12
|
+
update: jest.fn(),
|
|
13
|
+
delete: jest.fn()
|
|
14
|
+
}));
|
|
15
|
+
});
|
|
8
16
|
<%_ if (caching !== 'None') { -%>
|
|
9
17
|
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
18
|
get: jest.fn(),
|
|
@@ -26,11 +34,12 @@ describe('CreateUser UseCase', () => {
|
|
|
26
34
|
it('should create and save a new user', async () => {
|
|
27
35
|
const name = 'Test User';
|
|
28
36
|
const email = 'test@example.com';
|
|
37
|
+
const password = 'password123';
|
|
29
38
|
const expectedResult = { id: 1, name, email };
|
|
30
39
|
|
|
31
40
|
mockUserRepository.save.mockResolvedValue(expectedResult);
|
|
32
41
|
|
|
33
|
-
const result = await createUser.execute(name, email);
|
|
42
|
+
const result = await createUser.execute(name, email, password);
|
|
34
43
|
|
|
35
44
|
expect(mockUserRepository.save).toHaveBeenCalledTimes(1);
|
|
36
45
|
const savedUser = mockUserRepository.save.mock.calls[0][0];
|
|
@@ -46,6 +55,6 @@ describe('CreateUser UseCase', () => {
|
|
|
46
55
|
const error = new Error('Database error');
|
|
47
56
|
mockUserRepository.save.mockRejectedValue(error);
|
|
48
57
|
|
|
49
|
-
await expect(createUser.execute('Test', 'test@test.com')).rejects.toThrow(error);
|
|
58
|
+
await expect(createUser.execute('Test', 'test@test.com', 'pwd')).rejects.toThrow(error);
|
|
50
59
|
});
|
|
51
60
|
});
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<%_ if (caching !== 'None') { _%>
|
|
2
|
+
const cacheService = require('<% if (caching === "Redis") { %>../infrastructure/caching/redisClient<% } else { %>../infrastructure/caching/memoryCache<% } %>');
|
|
3
|
+
const logger = require('../infrastructure/log/logger');
|
|
4
|
+
<%_ } _%>
|
|
5
|
+
|
|
6
|
+
class DeleteUser {
|
|
7
|
+
constructor(userRepository) {
|
|
8
|
+
this.userRepository = userRepository;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async execute(id) {
|
|
12
|
+
const result = await this.userRepository.delete(id);
|
|
13
|
+
<%_ if (caching !== 'None') { -%>
|
|
14
|
+
if (result) {
|
|
15
|
+
try {
|
|
16
|
+
await cacheService.del('users:all');
|
|
17
|
+
await cacheService.del(`user:${id}`);
|
|
18
|
+
logger.info(`Invalidated cache for user ${id}`);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error('Cache error (del):', error);
|
|
21
|
+
}
|
|
22
|
+
}<%_ } -%>
|
|
23
|
+
return result;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = DeleteUser;
|
|
@@ -4,7 +4,15 @@ const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
|
4
4
|
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
5
|
<%_ } -%>
|
|
6
6
|
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository')
|
|
7
|
+
jest.mock('@/infrastructure/repositories/UserRepository', () => {
|
|
8
|
+
return jest.fn().mockImplementation(() => ({
|
|
9
|
+
save: jest.fn(),
|
|
10
|
+
findById: jest.fn(),
|
|
11
|
+
getUsers: jest.fn(),
|
|
12
|
+
update: jest.fn(),
|
|
13
|
+
delete: jest.fn()
|
|
14
|
+
}));
|
|
15
|
+
});
|
|
8
16
|
<%_ if (caching !== 'None') { -%>
|
|
9
17
|
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
18
|
get: jest.fn(),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<%_ if (caching !== 'None') { _%>
|
|
2
|
+
const cacheService = require('<% if (caching === "Redis") { %>../infrastructure/caching/redisClient<% } else { %>../infrastructure/caching/memoryCache<% } %>');
|
|
3
|
+
const logger = require('../infrastructure/log/logger');
|
|
4
|
+
<%_ } _%>
|
|
5
|
+
|
|
6
|
+
class GetAllUsers {
|
|
7
|
+
constructor(userRepository) {
|
|
8
|
+
this.userRepository = userRepository;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async execute() {
|
|
12
|
+
<%_ if (caching !== 'None') { -%>
|
|
13
|
+
const cacheKey = 'users:all';
|
|
14
|
+
try {
|
|
15
|
+
const cachedUsers = await cacheService.get(cacheKey);
|
|
16
|
+
if (cachedUsers) {
|
|
17
|
+
logger.info('Serving users from cache');
|
|
18
|
+
return cachedUsers;
|
|
19
|
+
}
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logger.error('Cache error (get):', error);
|
|
22
|
+
}<%_ } -%>
|
|
23
|
+
const users = await this.userRepository.getUsers();
|
|
24
|
+
<%_ if (caching !== 'None') { -%>
|
|
25
|
+
if (users) {
|
|
26
|
+
try {
|
|
27
|
+
await cacheService.set(cacheKey, users, 3600); // Cache for 1 hour
|
|
28
|
+
} catch (error) {
|
|
29
|
+
logger.error('Cache error (set):', error);
|
|
30
|
+
}
|
|
31
|
+
}<%_ } -%>
|
|
32
|
+
return users;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = GetAllUsers;
|
|
@@ -1,10 +1,32 @@
|
|
|
1
1
|
const GetAllUsers = require('@/usecases/GetAllUsers');
|
|
2
|
+
|
|
3
|
+
<% if (caching === 'Redis') { -%>
|
|
4
|
+
jest.mock('@/infrastructure/caching/redisClient', () => ({
|
|
5
|
+
get: jest.fn(),
|
|
6
|
+
set: jest.fn(),
|
|
7
|
+
del: jest.fn()
|
|
8
|
+
}));
|
|
9
|
+
<% } else if (caching === 'Memory Cache') { -%>
|
|
10
|
+
jest.mock('@/infrastructure/caching/memoryCache', () => ({
|
|
11
|
+
get: jest.fn(),
|
|
12
|
+
set: jest.fn(),
|
|
13
|
+
del: jest.fn()
|
|
14
|
+
}));
|
|
15
|
+
<% } -%>
|
|
2
16
|
const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
3
17
|
<%_ if (caching !== 'None') { -%>
|
|
4
18
|
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
19
|
<%_ } -%>
|
|
6
20
|
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository')
|
|
21
|
+
jest.mock('@/infrastructure/repositories/UserRepository', () => {
|
|
22
|
+
return jest.fn().mockImplementation(() => ({
|
|
23
|
+
save: jest.fn(),
|
|
24
|
+
findById: jest.fn(),
|
|
25
|
+
getUsers: jest.fn(),
|
|
26
|
+
update: jest.fn(),
|
|
27
|
+
delete: jest.fn()
|
|
28
|
+
}));
|
|
29
|
+
});
|
|
8
30
|
<%_ if (caching !== 'None') { -%>
|
|
9
31
|
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
32
|
get: jest.fn(),
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
<%_ if (caching !== 'None') { _%>
|
|
2
|
+
const cacheService = require('<% if (caching === "Redis") { %>../infrastructure/caching/redisClient<% } else { %>../infrastructure/caching/memoryCache<% } %>');
|
|
3
|
+
const logger = require('../infrastructure/log/logger');
|
|
4
|
+
<%_ } _%>
|
|
5
|
+
|
|
6
|
+
class GetUserById {
|
|
7
|
+
constructor(userRepository) {
|
|
8
|
+
this.userRepository = userRepository;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async execute(id) {
|
|
12
|
+
<%_ if (caching !== 'None') { -%>
|
|
13
|
+
const cacheKey = `user:${id}`;
|
|
14
|
+
try {
|
|
15
|
+
const cachedUser = await cacheService.get(cacheKey);
|
|
16
|
+
if (cachedUser) {
|
|
17
|
+
logger.info(`Serving user ${id} from cache`);
|
|
18
|
+
return cachedUser;
|
|
19
|
+
}
|
|
20
|
+
} catch (error) {
|
|
21
|
+
logger.error('Cache error (get):', error);
|
|
22
|
+
}<%_ } -%>
|
|
23
|
+
const user = await this.userRepository.findById(id);
|
|
24
|
+
<%_ if (caching !== 'None') { -%>
|
|
25
|
+
if (user) {
|
|
26
|
+
try {
|
|
27
|
+
await cacheService.set(cacheKey, user, 3600); // Cache for 1 hour
|
|
28
|
+
} catch (error) {
|
|
29
|
+
logger.error('Cache error (set):', error);
|
|
30
|
+
}
|
|
31
|
+
}<%_ } -%>
|
|
32
|
+
return user;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = GetUserById;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
const GetUserById = require('@/usecases/GetUserById');
|
|
2
|
+
|
|
3
|
+
<% if (caching === 'Redis') { -%>
|
|
4
|
+
jest.mock('@/infrastructure/caching/redisClient', () => ({
|
|
5
|
+
get: jest.fn(),
|
|
6
|
+
set: jest.fn(),
|
|
7
|
+
del: jest.fn()
|
|
8
|
+
}));
|
|
9
|
+
<% } else if (caching === 'Memory Cache') { -%>
|
|
10
|
+
jest.mock('@/infrastructure/caching/memoryCache', () => ({
|
|
11
|
+
get: jest.fn(),
|
|
12
|
+
set: jest.fn(),
|
|
13
|
+
del: jest.fn()
|
|
14
|
+
}));
|
|
15
|
+
<% } -%>
|
|
16
|
+
|
|
17
|
+
describe('GetUserById Use Case', () => {
|
|
18
|
+
let userRepository;
|
|
19
|
+
let getUserById;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
userRepository = {
|
|
23
|
+
findById: jest.fn(),
|
|
24
|
+
};
|
|
25
|
+
getUserById = new GetUserById(userRepository);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should return a user if found (Happy Path)', async () => {
|
|
29
|
+
const id = '1';
|
|
30
|
+
const user = { id, name: 'Test User', email: 'test@example.com' };
|
|
31
|
+
userRepository.findById.mockResolvedValue(user);
|
|
32
|
+
|
|
33
|
+
const result = await getUserById.execute(id);
|
|
34
|
+
|
|
35
|
+
expect(result).toEqual(user);
|
|
36
|
+
expect(userRepository.findById).toHaveBeenCalledWith(id);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return null if user not found (Error Handling)', async () => {
|
|
40
|
+
const id = '999';
|
|
41
|
+
userRepository.findById.mockResolvedValue(null);
|
|
42
|
+
|
|
43
|
+
const result = await getUserById.execute(id);
|
|
44
|
+
|
|
45
|
+
expect(result).toBeNull();
|
|
46
|
+
expect(userRepository.findById).toHaveBeenCalledWith(id);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<%_ if (caching !== 'None') { _%>
|
|
2
|
+
const cacheService = require('<% if (caching === "Redis") { %>../infrastructure/caching/redisClient<% } else { %>../infrastructure/caching/memoryCache<% } %>');
|
|
3
|
+
const logger = require('../infrastructure/log/logger');
|
|
4
|
+
<%_ } _%>
|
|
5
|
+
|
|
6
|
+
class UpdateUser {
|
|
7
|
+
constructor(userRepository) {
|
|
8
|
+
this.userRepository = userRepository;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
async execute(id, data) {
|
|
12
|
+
const user = await this.userRepository.update(id, data);
|
|
13
|
+
<%_ if (caching !== 'None') { -%>
|
|
14
|
+
if (user) {
|
|
15
|
+
try {
|
|
16
|
+
await cacheService.del('users:all');
|
|
17
|
+
await cacheService.del(`user:${id}`);
|
|
18
|
+
logger.info(`Invalidated cache for user ${id}`);
|
|
19
|
+
} catch (error) {
|
|
20
|
+
logger.error('Cache error (del):', error);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
<%_ } -%>
|
|
24
|
+
return user;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
module.exports = UpdateUser;
|
|
@@ -4,7 +4,15 @@ const UserRepository = require('@/infrastructure/repositories/UserRepository');
|
|
|
4
4
|
const cacheService = require('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>');
|
|
5
5
|
<%_ } -%>
|
|
6
6
|
|
|
7
|
-
jest.mock('@/infrastructure/repositories/UserRepository')
|
|
7
|
+
jest.mock('@/infrastructure/repositories/UserRepository', () => {
|
|
8
|
+
return jest.fn().mockImplementation(() => ({
|
|
9
|
+
save: jest.fn(),
|
|
10
|
+
findById: jest.fn(),
|
|
11
|
+
getUsers: jest.fn(),
|
|
12
|
+
update: jest.fn(),
|
|
13
|
+
delete: jest.fn()
|
|
14
|
+
}));
|
|
15
|
+
});
|
|
8
16
|
<%_ if (caching !== 'None') { -%>
|
|
9
17
|
jest.mock('<% if (caching === "Redis") { %>@/infrastructure/caching/redisClient<% } else { %>@/infrastructure/caching/memoryCache<% } %>', () => ({
|
|
10
18
|
get: jest.fn(),
|
|
@@ -5,6 +5,7 @@ const ERROR_MESSAGES = {
|
|
|
5
5
|
INTERNAL_SERVER_ERROR: 'Internal Server Error',
|
|
6
6
|
BAD_REQUEST: 'Bad Request',
|
|
7
7
|
FETCH_USERS_ERROR: 'Error fetching users',
|
|
8
|
+
FETCH_USER_ERROR: 'Error fetching user',
|
|
8
9
|
CREATE_USER_ERROR: 'Error creating user',
|
|
9
10
|
UPDATE_USER_ERROR: 'Error updating user',
|
|
10
11
|
DELETE_USER_ERROR: 'Error deleting user',
|
|
@@ -34,13 +34,22 @@ const envSchema = z.object({
|
|
|
34
34
|
<%_ if (communication === 'Kafka') { -%>
|
|
35
35
|
KAFKA_BROKER: z.string(),
|
|
36
36
|
<%_ } -%>
|
|
37
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
38
|
+
JWT_SECRET: z.string(),
|
|
39
|
+
JWT_EXPIRES_IN: z.string().default('15m'),
|
|
40
|
+
JWT_REFRESH_SECRET: z.string().default('your-secret-refresh-key'),
|
|
41
|
+
JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),
|
|
42
|
+
<%_ } -%>
|
|
37
43
|
});
|
|
38
44
|
|
|
39
45
|
const _env = envSchema.safeParse(process.env);
|
|
40
46
|
|
|
41
47
|
if (!_env.success) {
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
49
|
+
logger.error('❌ Invalid environment variables:', _env.error.format());
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
logger.warn('⚠️ Environment validation failed. Continuing in test mode.');
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
export const env = _env.data
|
|
55
|
+
export const env = (_env.success ? _env.data : process.env) as unknown as z.infer<typeof envSchema>;
|
|
@@ -13,6 +13,8 @@ import healthRoutes from '@/interfaces/routes/healthRoute';
|
|
|
13
13
|
import userRoutes from '@/interfaces/routes/userRoutes';
|
|
14
14
|
import swaggerUi from 'swagger-ui-express';
|
|
15
15
|
import swaggerSpecs from '@/config/swagger';<% } %>
|
|
16
|
+
<%_ if (auth.includes('JWT')) { -%>import authRoutes from '@/interfaces/routes/authRoutes';<%_ } -%>
|
|
17
|
+
|
|
16
18
|
<%_ if (communication === 'Kafka') { -%>import { kafkaService } from '@/infrastructure/messaging/kafkaClient';<%_ } -%>
|
|
17
19
|
<%_ if (communication === 'GraphQL') { -%>
|
|
18
20
|
import { ApolloServer } from '@apollo/server';
|
|
@@ -54,6 +56,8 @@ app.use(morgan('combined', { stream: { write: (message) => logger.info(message.t
|
|
|
54
56
|
<%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
|
|
55
57
|
app.use('/api/users', userRoutes);
|
|
56
58
|
<%_ } -%>
|
|
59
|
+
<%_ if (auth.includes('JWT')) { -%>app.use('/api/auth', authRoutes);<%_ } -%>
|
|
60
|
+
|
|
57
61
|
<%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
|
|
58
62
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
|
|
59
63
|
<%_ } -%>
|