nodejs-quickstart-structure 1.19.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +320 -301
  2. package/LICENSE +15 -15
  3. package/README.md +45 -10
  4. package/bin/index.js +7 -1
  5. package/lib/generator.js +139 -139
  6. package/lib/modules/app-setup.js +401 -401
  7. package/lib/modules/config-files.js +151 -151
  8. package/lib/modules/database-setup.js +116 -116
  9. package/lib/modules/project-setup.js +32 -32
  10. package/lib/prompts.js +100 -100
  11. package/package.json +79 -78
  12. package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
  13. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
  14. package/templates/clean-architecture/js/src/index.js.ejs +55 -55
  15. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
  16. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
  17. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
  18. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
  19. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
  20. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
  21. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
  22. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
  23. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
  24. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
  25. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
  26. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
  27. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
  28. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
  29. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
  30. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
  31. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
  32. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
  33. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
  34. package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
  35. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
  36. package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
  37. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
  38. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
  39. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
  40. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
  41. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
  42. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
  43. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
  44. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
  45. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
  46. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
  47. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
  48. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
  49. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  50. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
  51. package/templates/common/.cursorrules.ejs +60 -60
  52. package/templates/common/.dockerignore +12 -12
  53. package/templates/common/.env.example.ejs +41 -41
  54. package/templates/common/.gitlab-ci.yml.ejs +86 -86
  55. package/templates/common/.lintstagedrc +6 -6
  56. package/templates/common/.prettierrc +7 -7
  57. package/templates/common/Dockerfile +73 -73
  58. package/templates/common/Jenkinsfile.ejs +87 -87
  59. package/templates/common/SECURITY.md +20 -20
  60. package/templates/common/_github/workflows/ci.yml.ejs +46 -46
  61. package/templates/common/_github/workflows/security.yml.ejs +36 -36
  62. package/templates/common/_gitignore +5 -5
  63. package/templates/common/_husky/pre-commit +4 -4
  64. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
  65. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
  66. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
  67. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
  68. package/templates/common/caching/js/memoryCache.js.ejs +60 -60
  69. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
  70. package/templates/common/caching/js/redisClient.js.ejs +75 -75
  71. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
  72. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
  73. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
  74. package/templates/common/database/js/database.js.ejs +19 -19
  75. package/templates/common/database/js/database.spec.js.ejs +56 -56
  76. package/templates/common/database/js/mongoose.js.ejs +33 -33
  77. package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
  78. package/templates/common/database/ts/database.spec.ts.ejs +56 -56
  79. package/templates/common/database/ts/database.ts.ejs +21 -21
  80. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
  81. package/templates/common/database/ts/mongoose.ts.ejs +28 -28
  82. package/templates/common/docker-compose.yml.ejs +159 -159
  83. package/templates/common/ecosystem.config.js.ejs +40 -40
  84. package/templates/common/eslint.config.mjs.ejs +77 -77
  85. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
  86. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
  87. package/templates/common/jest.config.js.ejs +32 -32
  88. package/templates/common/kafka/js/config/kafka.js +9 -9
  89. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
  90. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
  91. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
  92. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
  93. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
  94. package/templates/common/kafka/ts/config/kafka.ts +7 -7
  95. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
  96. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
  97. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
  98. package/templates/common/migrate-mongo-config.js.ejs +31 -31
  99. package/templates/common/migrations/init.js.ejs +23 -23
  100. package/templates/common/package.json.ejs +119 -118
  101. package/templates/common/prompts/add-feature.md.ejs +26 -26
  102. package/templates/common/prompts/project-context.md.ejs +43 -43
  103. package/templates/common/prompts/troubleshoot.md.ejs +28 -28
  104. package/templates/common/public/css/style.css +147 -147
  105. package/templates/common/scripts/run-e2e.js.ejs +63 -63
  106. package/templates/common/sonar-project.properties.ejs +27 -27
  107. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
  108. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
  109. package/templates/common/tsconfig.json +22 -22
  110. package/templates/common/views/ejs/index.ejs +55 -55
  111. package/templates/common/views/pug/index.pug +40 -40
  112. package/templates/mvc/js/src/config/env.js.ejs +46 -46
  113. package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
  114. package/templates/mvc/js/src/errors/ApiError.js +14 -14
  115. package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
  116. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
  117. package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
  118. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
  119. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
  120. package/templates/mvc/js/src/index.js.ejs +136 -136
  121. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
  122. package/templates/mvc/js/src/utils/httpCodes.js +9 -9
  123. package/templates/mvc/js/src/utils/logger.js +40 -40
  124. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
  125. package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
  126. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
  127. package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
  128. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
  129. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
  130. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
  131. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
  132. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
  133. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  134. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
  135. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
  136. package/templates/mvc/ts/src/utils/logger.ts +36 -36
@@ -1,70 +1,70 @@
1
- const request = require('supertest');
2
- const express = require('express');
3
- <% if (architecture === 'MVC') { -%>
4
- const healthRoute = require('@/routes/healthRoute');
5
- <% } else { -%>
6
- const healthRoute = require('@/interfaces/routes/healthRoute');
7
- <% } -%>
8
- const HTTP_STATUS = require('@/utils/httpCodes');
9
-
10
- <%_ if (database === 'MongoDB') { -%>
11
- jest.mock('mongoose', () => {
12
- return {
13
- connection: {
14
- readyState: 1,
15
- db: {
16
- admin: jest.fn().mockReturnValue({
17
- ping: jest.fn().mockResolvedValue(true)
18
- })
19
- }
20
- }
21
- };
22
- });
23
- <%_ } else if (database !== 'None') { -%>
24
- jest.mock('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>', () => {
25
- return {
26
- authenticate: jest.fn()
27
- };
28
- });
29
- <%_ } -%>
30
-
31
- describe('Health Route', () => {
32
- let app;
33
-
34
- beforeEach(() => {
35
- app = express();
36
- app.use('/health', healthRoute);
37
- jest.clearAllMocks();
38
- });
39
-
40
- it('should return 200 OK with UP status', async () => {
41
- const res = await request(app).get('/health');
42
- expect(res.status).toBe(HTTP_STATUS.OK);
43
- expect(res.body.status).toBe('UP');
44
- expect(res.body.database).toBe('<% if (database === "None") { %>None<% } else { %>connected<% } %>');
45
- });
46
-
47
- <%_ if (database === 'MongoDB') { -%>
48
- it('should handle database ping failure and return 500', async () => {
49
- const mongoose = require('mongoose');
50
- mongoose.connection.db.admin.mockReturnValueOnce({
51
- ping: jest.fn().mockRejectedValueOnce(new Error('DB Error'))
52
- });
53
-
54
- const res = await request(app).get('/health');
55
- expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
56
- expect(res.body.status).toBe('DOWN');
57
- expect(res.body.database).toBe('error');
58
- });
59
- <%_ } else if (database !== 'None') { -%>
60
- it('should handle database authentication failure and return 500', async () => {
61
- const sequelize = require('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>');
62
- sequelize.authenticate.mockRejectedValueOnce(new Error('DB Error'));
63
-
64
- const res = await request(app).get('/health');
65
- expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
66
- expect(res.body.status).toBe('DOWN');
67
- expect(res.body.database).toBe('error');
68
- });
69
- <%_ } -%>
70
- });
1
+ const request = require('supertest');
2
+ const express = require('express');
3
+ <% if (architecture === 'MVC') { -%>
4
+ const healthRoute = require('@/routes/healthRoute');
5
+ <% } else { -%>
6
+ const healthRoute = require('@/interfaces/routes/healthRoute');
7
+ <% } -%>
8
+ const HTTP_STATUS = require('@/utils/httpCodes');
9
+
10
+ <%_ if (database === 'MongoDB') { -%>
11
+ jest.mock('mongoose', () => {
12
+ return {
13
+ connection: {
14
+ readyState: 1,
15
+ db: {
16
+ admin: jest.fn().mockReturnValue({
17
+ ping: jest.fn().mockResolvedValue(true)
18
+ })
19
+ }
20
+ }
21
+ };
22
+ });
23
+ <%_ } else if (database !== 'None') { -%>
24
+ jest.mock('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>', () => {
25
+ return {
26
+ authenticate: jest.fn()
27
+ };
28
+ });
29
+ <%_ } -%>
30
+
31
+ describe('Health Route', () => {
32
+ let app;
33
+
34
+ beforeEach(() => {
35
+ app = express();
36
+ app.use('/health', healthRoute);
37
+ jest.clearAllMocks();
38
+ });
39
+
40
+ it('should return 200 OK with UP status', async () => {
41
+ const res = await request(app).get('/health');
42
+ expect(res.status).toBe(HTTP_STATUS.OK);
43
+ expect(res.body.status).toBe('UP');
44
+ expect(res.body.database).toBe('<% if (database === "None") { %>None<% } else { %>connected<% } %>');
45
+ });
46
+
47
+ <%_ if (database === 'MongoDB') { -%>
48
+ it('should handle database ping failure and return 500', async () => {
49
+ const mongoose = require('mongoose');
50
+ mongoose.connection.db.admin.mockReturnValueOnce({
51
+ ping: jest.fn().mockRejectedValueOnce(new Error('DB Error'))
52
+ });
53
+
54
+ const res = await request(app).get('/health');
55
+ expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
56
+ expect(res.body.status).toBe('DOWN');
57
+ expect(res.body.database).toBe('error');
58
+ });
59
+ <%_ } else if (database !== 'None') { -%>
60
+ it('should handle database authentication failure and return 500', async () => {
61
+ const sequelize = require('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>');
62
+ sequelize.authenticate.mockRejectedValueOnce(new Error('DB Error'));
63
+
64
+ const res = await request(app).get('/health');
65
+ expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
66
+ expect(res.body.status).toBe('DOWN');
67
+ expect(res.body.database).toBe('error');
68
+ });
69
+ <%_ } -%>
70
+ });
@@ -1,76 +1,76 @@
1
- import request from 'supertest';
2
- import express from 'express';
3
- <% if (architecture === 'MVC') { -%>
4
- import healthRoute from '@/routes/healthRoute';
5
- <% } else { -%>
6
- import healthRoute from '@/interfaces/routes/healthRoute';
7
- <% } -%>
8
- import { HTTP_STATUS } from '@/utils/httpCodes';
9
- <%_ if (database === 'MongoDB') { -%>
10
- import mongoose from 'mongoose';
11
- <%_ } else if (database !== 'None') { -%>
12
- import sequelize from '<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>';
13
- <%_ } -%>
14
-
15
- <%_ if (database === 'MongoDB') { -%>
16
- jest.mock('mongoose', () => {
17
- return {
18
- connection: {
19
- readyState: 1,
20
- db: {
21
- admin: jest.fn().mockReturnValue({
22
- ping: jest.fn().mockResolvedValue(true)
23
- })
24
- }
25
- }
26
- };
27
- });
28
- <%_ } else if (database !== 'None') { -%>
29
- jest.mock('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>', () => {
30
- return {
31
- __esModule: true,
32
- default: {
33
- authenticate: jest.fn()
34
- }
35
- };
36
- });
37
- <%_ } -%>
38
-
39
- describe('Health Route', () => {
40
- let app: express.Express;
41
-
42
- beforeEach(() => {
43
- app = express();
44
- app.use('/health', healthRoute);
45
- jest.clearAllMocks();
46
- });
47
-
48
- it('should return 200 OK with UP status', async () => {
49
- const res = await request(app).get('/health');
50
- expect(res.status).toBe(HTTP_STATUS.OK);
51
- expect(res.body.status).toBe('UP');
52
- expect(res.body.database).toBe('<% if (database === "None") { %>None<% } else { %>connected<% } %>');
53
- });
54
-
55
- <%_ if (database === 'MongoDB') { -%>
56
- it('should handle database ping failure and return 500', async () => {
57
- ((mongoose.connection.db as any).admin as jest.Mock).mockReturnValueOnce({
58
- ping: jest.fn().mockRejectedValueOnce(new Error('DB Error'))
59
- });
60
-
61
- const res = await request(app).get('/health');
62
- expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
63
- expect(res.body.status).toBe('DOWN');
64
- expect(res.body.database).toBe('error');
65
- });
66
- <%_ } else if (database !== 'None') { -%>
67
- it('should handle database authentication failure and return 500', async () => {
68
- (sequelize.authenticate as jest.Mock).mockRejectedValueOnce(new Error('DB Error'));
69
-
70
- const res = await request(app).get('/health');
71
- expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
72
- expect(res.body.status).toBe('DOWN');
73
- expect(res.body.database).toBe('error');
74
- });
75
- <%_ } -%>
76
- });
1
+ import request from 'supertest';
2
+ import express from 'express';
3
+ <% if (architecture === 'MVC') { -%>
4
+ import healthRoute from '@/routes/healthRoute';
5
+ <% } else { -%>
6
+ import healthRoute from '@/interfaces/routes/healthRoute';
7
+ <% } -%>
8
+ import { HTTP_STATUS } from '@/utils/httpCodes';
9
+ <%_ if (database === 'MongoDB') { -%>
10
+ import mongoose from 'mongoose';
11
+ <%_ } else if (database !== 'None') { -%>
12
+ import sequelize from '<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>';
13
+ <%_ } -%>
14
+
15
+ <%_ if (database === 'MongoDB') { -%>
16
+ jest.mock('mongoose', () => {
17
+ return {
18
+ connection: {
19
+ readyState: 1,
20
+ db: {
21
+ admin: jest.fn().mockReturnValue({
22
+ ping: jest.fn().mockResolvedValue(true)
23
+ })
24
+ }
25
+ }
26
+ };
27
+ });
28
+ <%_ } else if (database !== 'None') { -%>
29
+ jest.mock('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>', () => {
30
+ return {
31
+ __esModule: true,
32
+ default: {
33
+ authenticate: jest.fn()
34
+ }
35
+ };
36
+ });
37
+ <%_ } -%>
38
+
39
+ describe('Health Route', () => {
40
+ let app: express.Express;
41
+
42
+ beforeEach(() => {
43
+ app = express();
44
+ app.use('/health', healthRoute);
45
+ jest.clearAllMocks();
46
+ });
47
+
48
+ it('should return 200 OK with UP status', async () => {
49
+ const res = await request(app).get('/health');
50
+ expect(res.status).toBe(HTTP_STATUS.OK);
51
+ expect(res.body.status).toBe('UP');
52
+ expect(res.body.database).toBe('<% if (database === "None") { %>None<% } else { %>connected<% } %>');
53
+ });
54
+
55
+ <%_ if (database === 'MongoDB') { -%>
56
+ it('should handle database ping failure and return 500', async () => {
57
+ ((mongoose.connection.db as any).admin as jest.Mock).mockReturnValueOnce({
58
+ ping: jest.fn().mockRejectedValueOnce(new Error('DB Error'))
59
+ });
60
+
61
+ const res = await request(app).get('/health');
62
+ expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
63
+ expect(res.body.status).toBe('DOWN');
64
+ expect(res.body.database).toBe('error');
65
+ });
66
+ <%_ } else if (database !== 'None') { -%>
67
+ it('should handle database authentication failure and return 500', async () => {
68
+ (sequelize.authenticate as jest.Mock).mockRejectedValueOnce(new Error('DB Error'));
69
+
70
+ const res = await request(app).get('/health');
71
+ expect(res.status).toBe(HTTP_STATUS.INTERNAL_SERVER_ERROR);
72
+ expect(res.body.status).toBe('DOWN');
73
+ expect(res.body.database).toBe('error');
74
+ });
75
+ <%_ } -%>
76
+ });
@@ -1,32 +1,32 @@
1
- module.exports = {
2
- testEnvironment: 'node',
3
- coverageDirectory: 'coverage',
4
- collectCoverageFrom: ['src/**/*.{js,ts}'],
5
- testMatch: ['**/*.test.ts', '**/*.test.js', '**/*.spec.ts', '**/*.spec.js'],
6
- testPathIgnorePatterns: ['/node_modules/', '/tests/e2e/'],
7
- <% if (language === 'TypeScript') { %>preset: 'ts-jest',<% } %>
8
- moduleNameMapper: {
9
- '^@/(.*)$': '<rootDir>/src/$1',
10
- },
11
- coveragePathIgnorePatterns: [
12
- "/node_modules/",
13
- "/dist/",
14
- "src/index",
15
- "src/app",
16
- "src/config/env",
17
- "src/infrastructure/config/env",
18
- "src/config/swagger",
19
- "src/infrastructure/webserver/swagger",
20
- "src/infrastructure/webserver/server",
21
- "src/utils/logger",
22
- "src/infrastructure/log/logger"
23
- ],
24
- coverageThreshold: {
25
- global: {
26
- branches: 70,
27
- functions: 80,
28
- lines: 80,
29
- statements: 80
30
- }
31
- }
32
- };
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ coverageDirectory: 'coverage',
4
+ collectCoverageFrom: ['src/**/*.{js,ts}'],
5
+ testMatch: ['**/*.test.ts', '**/*.test.js', '**/*.spec.ts', '**/*.spec.js'],
6
+ testPathIgnorePatterns: ['/node_modules/', '/tests/e2e/'],
7
+ <% if (language === 'TypeScript') { %>preset: 'ts-jest',<% } %>
8
+ moduleNameMapper: {
9
+ '^@/(.*)$': '<rootDir>/src/$1',
10
+ },
11
+ coveragePathIgnorePatterns: [
12
+ "/node_modules/",
13
+ "/dist/",
14
+ "src/index",
15
+ "src/app",
16
+ "src/config/env",
17
+ "src/infrastructure/config/env",
18
+ "src/config/swagger",
19
+ "src/infrastructure/webserver/swagger",
20
+ "src/infrastructure/webserver/server",
21
+ "src/utils/logger",
22
+ "src/infrastructure/log/logger"
23
+ ],
24
+ coverageThreshold: {
25
+ global: {
26
+ branches: 70,
27
+ functions: 80,
28
+ lines: 80,
29
+ statements: 80
30
+ }
31
+ }
32
+ };
@@ -1,9 +1,9 @@
1
- const { Kafka } = require('kafkajs');
2
- const { env } = require('./env');
3
-
4
- const kafka = new Kafka({
5
- clientId: 'nodejs-service',
6
- brokers: [env.KAFKA_BROKER]
7
- });
8
-
9
- module.exports = { kafka };
1
+ const { Kafka } = require('kafkajs');
2
+ const { env } = require('./env');
3
+
4
+ const kafka = new Kafka({
5
+ clientId: 'nodejs-service',
6
+ brokers: [env.KAFKA_BROKER]
7
+ });
8
+
9
+ module.exports = { kafka };
@@ -1,27 +1,27 @@
1
- const { Kafka } = require('kafkajs');
2
-
3
- jest.mock('kafkajs', () => {
4
- return {
5
- Kafka: jest.fn().mockImplementation(() => ({
6
- producer: jest.fn(),
7
- consumer: jest.fn(),
8
- })),
9
- };
10
- });
11
-
12
- jest.mock('<% if (architecture === "MVC") { %>@/config/env<% } else { %>@/infrastructure/config/env<% } %>', () => ({
13
- env: {
14
- KAFKA_BROKER: 'localhost:9092'
15
- }
16
- }));
17
-
18
- describe('Kafka Configuration', () => {
19
- beforeEach(() => {
20
- jest.clearAllMocks();
21
- });
22
-
23
- it('should initialize Kafka', () => {
24
- require('<% if (architecture === "MVC") { %>@/config/kafka<% } else { %>@/infrastructure/config/kafka<% } %>');
25
- expect(Kafka).toHaveBeenCalled();
26
- });
27
- });
1
+ const { Kafka } = require('kafkajs');
2
+
3
+ jest.mock('kafkajs', () => {
4
+ return {
5
+ Kafka: jest.fn().mockImplementation(() => ({
6
+ producer: jest.fn(),
7
+ consumer: jest.fn(),
8
+ })),
9
+ };
10
+ });
11
+
12
+ jest.mock('<% if (architecture === "MVC") { %>@/config/env<% } else { %>@/infrastructure/config/env<% } %>', () => ({
13
+ env: {
14
+ KAFKA_BROKER: 'localhost:9092'
15
+ }
16
+ }));
17
+
18
+ describe('Kafka Configuration', () => {
19
+ beforeEach(() => {
20
+ jest.clearAllMocks();
21
+ });
22
+
23
+ it('should initialize Kafka', () => {
24
+ require('<% if (architecture === "MVC") { %>@/config/kafka<% } else { %>@/infrastructure/config/kafka<% } %>');
25
+ expect(Kafka).toHaveBeenCalled();
26
+ });
27
+ });
@@ -1,58 +1,58 @@
1
- const BaseConsumer = require('<% if (architecture === "Clean Architecture") { %>@/interfaces/messaging/baseConsumer<% } else { %>@/messaging/baseConsumer<% } %>');
2
- const logger = require('<% if (architecture === "Clean Architecture") { %>@/infrastructure/log/logger<% } else { %>@/utils/logger<% } %>');
3
-
4
- jest.mock('<% if (architecture === "Clean Architecture") { %>@/infrastructure/log/logger<% } else { %>@/utils/logger<% } %>');
5
-
6
- class TestConsumer extends BaseConsumer {
7
- constructor() {
8
- super();
9
- this._topic = 'test-topic';
10
- }
11
- get topic() { return this._topic; }
12
- get groupId() { return 'test-group'; }
13
- async handle(data) {
14
- logger.info('Handled', data);
15
- }
16
- }
17
-
18
- describe('BaseConsumer', () => {
19
- let consumer;
20
-
21
- beforeEach(() => {
22
- jest.clearAllMocks();
23
- consumer = new TestConsumer();
24
- });
25
-
26
- it('should throw error if instantiated directly', () => {
27
- expect(() => new BaseConsumer()).toThrow("Abstract class 'BaseConsumer' cannot be instantiated.");
28
- });
29
-
30
- it('should process a valid message', async () => {
31
- const message = { value: Buffer.from(JSON.stringify({ test: 'data' })) };
32
- await consumer.onMessage({ message });
33
- expect(logger.info).toHaveBeenCalledWith('Handled', { test: 'data' });
34
- });
35
-
36
- it('should handle invalid JSON', async () => {
37
- const message = { value: Buffer.from('invalid-json') };
38
- await consumer.onMessage({ message });
39
- expect(logger.error).toHaveBeenCalledWith(
40
- expect.stringContaining('[Kafka] Error processing message on topic test-topic:'),
41
- expect.anything()
42
- );
43
- });
44
-
45
- it('should skip empty messages', async () => {
46
- const message = { value: null };
47
- await consumer.onMessage({ message });
48
- expect(logger.info).not.toHaveBeenCalled();
49
- });
50
-
51
- it('should throw if topic, groupId or handle are not implemented', async () => {
52
- class IncompleteConsumer extends BaseConsumer {}
53
- const incomplete = new IncompleteConsumer();
54
- expect(() => incomplete.topic).toThrow("Property 'topic' must be implemented");
55
- expect(() => incomplete.groupId).toThrow("Property 'groupId' must be implemented");
56
- await expect(incomplete.handle({})).rejects.toThrow("Method 'handle()' must be implemented");
57
- });
58
- });
1
+ const BaseConsumer = require('<% if (architecture === "Clean Architecture") { %>@/interfaces/messaging/baseConsumer<% } else { %>@/messaging/baseConsumer<% } %>');
2
+ const logger = require('<% if (architecture === "Clean Architecture") { %>@/infrastructure/log/logger<% } else { %>@/utils/logger<% } %>');
3
+
4
+ jest.mock('<% if (architecture === "Clean Architecture") { %>@/infrastructure/log/logger<% } else { %>@/utils/logger<% } %>');
5
+
6
+ class TestConsumer extends BaseConsumer {
7
+ constructor() {
8
+ super();
9
+ this._topic = 'test-topic';
10
+ }
11
+ get topic() { return this._topic; }
12
+ get groupId() { return 'test-group'; }
13
+ async handle(data) {
14
+ logger.info('Handled', data);
15
+ }
16
+ }
17
+
18
+ describe('BaseConsumer', () => {
19
+ let consumer;
20
+
21
+ beforeEach(() => {
22
+ jest.clearAllMocks();
23
+ consumer = new TestConsumer();
24
+ });
25
+
26
+ it('should throw error if instantiated directly', () => {
27
+ expect(() => new BaseConsumer()).toThrow("Abstract class 'BaseConsumer' cannot be instantiated.");
28
+ });
29
+
30
+ it('should process a valid message', async () => {
31
+ const message = { value: Buffer.from(JSON.stringify({ test: 'data' })) };
32
+ await consumer.onMessage({ message });
33
+ expect(logger.info).toHaveBeenCalledWith('Handled', { test: 'data' });
34
+ });
35
+
36
+ it('should handle invalid JSON', async () => {
37
+ const message = { value: Buffer.from('invalid-json') };
38
+ await consumer.onMessage({ message });
39
+ expect(logger.error).toHaveBeenCalledWith(
40
+ expect.stringContaining('[Kafka] Error processing message on topic test-topic:'),
41
+ expect.anything()
42
+ );
43
+ });
44
+
45
+ it('should skip empty messages', async () => {
46
+ const message = { value: null };
47
+ await consumer.onMessage({ message });
48
+ expect(logger.info).not.toHaveBeenCalled();
49
+ });
50
+
51
+ it('should throw if topic, groupId or handle are not implemented', async () => {
52
+ class IncompleteConsumer extends BaseConsumer {}
53
+ const incomplete = new IncompleteConsumer();
54
+ expect(() => incomplete.topic).toThrow("Property 'topic' must be implemented");
55
+ expect(() => incomplete.groupId).toThrow("Property 'groupId' must be implemented");
56
+ await expect(incomplete.handle({})).rejects.toThrow("Method 'handle()' must be implemented");
57
+ });
58
+ });
@@ -1,27 +1,27 @@
1
- const { UserEventSchema } = require('<% if (architecture === "Clean Architecture") { %>@/interfaces/messaging/schemas/userEventSchema<% } else { %>@/messaging/schemas/userEventSchema<% } %>');
2
-
3
- describe('UserEventSchema', () => {
4
- it('should validate a correct USER_CREATED event', () => {
5
- const validEvent = {
6
- action: 'USER_CREATED',
7
- payload: {
8
- id: 1,
9
- email: 'test@example.com'
10
- }
11
- };
12
- const result = UserEventSchema.safeParse(validEvent);
13
- expect(result.success).toBe(true);
14
- });
15
-
16
- it('should fail validation for invalid email', () => {
17
- const invalidEvent = {
18
- action: 'USER_CREATED',
19
- payload: {
20
- id: 1,
21
- email: 'invalid-email'
22
- }
23
- };
24
- const result = UserEventSchema.safeParse(invalidEvent);
25
- expect(result.success).toBe(false);
26
- });
27
- });
1
+ const { UserEventSchema } = require('<% if (architecture === "Clean Architecture") { %>@/interfaces/messaging/schemas/userEventSchema<% } else { %>@/messaging/schemas/userEventSchema<% } %>');
2
+
3
+ describe('UserEventSchema', () => {
4
+ it('should validate a correct USER_CREATED event', () => {
5
+ const validEvent = {
6
+ action: 'USER_CREATED',
7
+ payload: {
8
+ id: 1,
9
+ email: 'test@example.com'
10
+ }
11
+ };
12
+ const result = UserEventSchema.safeParse(validEvent);
13
+ expect(result.success).toBe(true);
14
+ });
15
+
16
+ it('should fail validation for invalid email', () => {
17
+ const invalidEvent = {
18
+ action: 'USER_CREATED',
19
+ payload: {
20
+ id: 1,
21
+ email: 'invalid-email'
22
+ }
23
+ };
24
+ const result = UserEventSchema.safeParse(invalidEvent);
25
+ expect(result.success).toBe(false);
26
+ });
27
+ });