nodejs-quickstart-structure 1.15.1 → 1.16.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +14 -5
  3. package/lib/modules/app-setup.js +3 -3
  4. package/lib/modules/config-files.js +2 -2
  5. package/lib/modules/kafka-setup.js +70 -24
  6. package/package.json +1 -1
  7. package/templates/clean-architecture/js/src/index.js.ejs +9 -6
  8. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +12 -11
  9. package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +17 -1
  10. package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +36 -0
  11. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +1 -1
  12. package/templates/clean-architecture/ts/src/index.ts.ejs +16 -16
  13. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +0 -1
  14. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +19 -0
  15. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +17 -0
  16. package/templates/common/Dockerfile +2 -0
  17. package/templates/common/README.md.ejs +24 -1
  18. package/templates/common/database/js/models/User.js.ejs +2 -1
  19. package/templates/common/database/ts/models/User.ts.ejs +4 -3
  20. package/templates/common/eslint.config.mjs.ejs +30 -3
  21. package/templates/common/health/js/healthRoute.js.ejs +5 -2
  22. package/templates/common/health/ts/healthRoute.ts.ejs +5 -2
  23. package/templates/common/jest.config.js.ejs +4 -1
  24. package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +30 -0
  25. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -0
  26. package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +11 -0
  27. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -0
  28. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +31 -0
  29. package/templates/common/kafka/js/messaging/welcomeEmailConsumer.spec.js.ejs +49 -0
  30. package/templates/common/kafka/js/services/kafkaService.js.ejs +77 -23
  31. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +53 -7
  32. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -0
  33. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -0
  34. package/templates/common/kafka/ts/messaging/userEventSchema.spec.ts.ejs +51 -0
  35. package/templates/common/kafka/ts/messaging/userEventSchema.ts.ejs +11 -0
  36. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.spec.ts.ejs +49 -0
  37. package/templates/common/kafka/ts/messaging/welcomeEmailConsumer.ts.ejs +25 -0
  38. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +22 -2
  39. package/templates/common/kafka/ts/services/kafkaService.ts.ejs +65 -12
  40. package/templates/common/package.json.ejs +6 -4
  41. package/templates/common/shutdown/ts/gracefulShutdown.ts.ejs +8 -11
  42. package/templates/mvc/js/src/controllers/userController.js.ejs +15 -0
  43. package/templates/mvc/js/src/controllers/userController.spec.js.ejs +39 -0
  44. package/templates/mvc/js/src/index.js.ejs +20 -15
  45. package/templates/mvc/ts/src/config/swagger.ts.ejs +1 -1
  46. package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +18 -0
  47. package/templates/mvc/ts/src/controllers/userController.ts.ejs +16 -0
  48. package/templates/mvc/ts/src/index.ts.ejs +16 -18
  49. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +0 -1
@@ -24,6 +24,20 @@ jest.mock('@/config/memoryCache', () => ({
24
24
  }));
25
25
  <%_ } -%>
26
26
  jest.mock('@/utils/logger');
27
+ <%_ if (communication === 'Kafka') { -%>
28
+ jest.mock('@/services/kafkaService', () => {
29
+ const mockSendMessage = jest.fn().mockResolvedValue(undefined);
30
+ return {
31
+ kafkaService: {
32
+ sendMessage: mockSendMessage
33
+ },
34
+ KafkaService: jest.fn().mockImplementation(() => ({
35
+ sendMessage: mockSendMessage
36
+ }))
37
+ };
38
+ });
39
+ <%_ } -%>
40
+
27
41
 
28
42
  describe('UserController', () => {
29
43
  let userController: UserController;
@@ -158,6 +172,10 @@ describe('UserController', () => {
158
172
  <% } -%>
159
173
  <%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
160
174
  expect(cacheService.del).toHaveBeenCalledWith('users:all');
175
+ <%_ } -%>
176
+ <%_ if (communication === 'Kafka') { -%>
177
+ const { kafkaService } = require('@/services/kafkaService');
178
+ expect(kafkaService.sendMessage).toHaveBeenCalled();
161
179
  <%_ } -%>
162
180
  });
163
181
 
@@ -8,6 +8,8 @@ import logger from '@/utils/logger';
8
8
  import cacheService from '@/config/redisClient';
9
9
  <%_ } else if (caching === 'Memory Cache') { -%>
10
10
  import cacheService from '@/config/memoryCache';
11
+ <%_ } -%><%_ if (communication === 'Kafka') { -%>
12
+ import { kafkaService } from '@/services/kafkaService';
11
13
  <%_ } -%>
12
14
 
13
15
  export class UserController {
@@ -42,6 +44,13 @@ export class UserController {
42
44
  const user = await User.create({ name, email });
43
45
  <%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
44
46
  await cacheService.del('users:all');
47
+ <%_ } -%>
48
+ <%_ if (communication === 'Kafka') { -%>
49
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
50
+ action: 'USER_CREATED',
51
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
52
+ payload: { id: (user as any).id || (user as any)._id, email: user.email }
53
+ }));
45
54
  <%_ } -%>
46
55
  return user;
47
56
  } catch (error) {
@@ -80,6 +89,13 @@ export class UserController {
80
89
  const user = await User.create({ name, email });
81
90
  <%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
82
91
  await cacheService.del('users:all');
92
+ <%_ } -%>
93
+ <%_ if (communication === 'Kafka') { -%>
94
+ await kafkaService.sendMessage('user-topic', JSON.stringify({
95
+ action: 'USER_CREATED',
96
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
97
+ payload: { id: (user as any).id || (user as any)._id, email: user.email }
98
+ }));
83
99
  <%_ } -%>
84
100
  res.status(HTTP_STATUS.CREATED).json(user);
85
101
  } catch (error) {
@@ -9,12 +9,11 @@ import morgan from 'morgan';
9
9
  import { errorMiddleware } from '@/utils/errorMiddleware';
10
10
  import { setupGracefulShutdown } from '@/utils/gracefulShutdown';
11
11
  import healthRoutes from '@/routes/healthRoute';
12
- <%_ if (communication === 'REST APIs') { -%>
13
- import apiRoutes from '@/routes/api';<%_ } -%>
14
- <% if (communication === 'REST APIs') { %>
12
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
13
+ import apiRoutes from '@/routes/api';
15
14
  import swaggerUi from 'swagger-ui-express';
16
- import swaggerSpecs from '@/config/swagger';<% } -%>
17
- <%_ if (communication === 'Kafka') { -%>import { KafkaService } from '@/services/kafkaService';<%_ } -%>
15
+ import swaggerSpecs from '@/config/swagger';<%_ } %>
16
+ <%_ if (communication === 'Kafka') { -%>import { kafkaService } from '@/services/kafkaService';<%_ } -%>
18
17
  <%_ if (communication === 'GraphQL') { -%>
19
18
  import { ApolloServer } from '@apollo/server';
20
19
  import { expressMiddleware } from '@apollo/server/express4';
@@ -51,7 +50,7 @@ app.use(limiter);
51
50
 
52
51
  app.use(express.json());
53
52
  app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
54
- <%_ if (communication === 'REST APIs') { -%>
53
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
55
54
  app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
56
55
  <%_ } -%>
57
56
  <%_ if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
@@ -60,7 +59,7 @@ import path from 'path';
60
59
  app.set('views', path.join(__dirname, 'views'));
61
60
  app.set('view engine', '<%= viewEngine.toLowerCase() %>');
62
61
  app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
63
- <%_ if (communication === 'REST APIs') { -%>
62
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
64
63
  app.use('/api', apiRoutes);
65
64
  <%_ } -%><% if (viewEngine && viewEngine !== 'None') { -%>
66
65
  app.get('/', (req: Request, res: Response) => {
@@ -106,18 +105,16 @@ const startServer = async () => {
106
105
  app.use('/graphql', expressMiddleware(apolloServer, { context: gqlContext }));
107
106
  <%_ } -%>
108
107
  app.use(errorMiddleware);
109
- <%_ if (communication === 'Kafka') { -%>
110
- const kafkaService = new KafkaService();
111
- <%_ } -%>
112
108
  const server = app.listen(port, () => {
113
109
  logger.info(`Server running on port ${port}`);
114
110
  <%_ if (communication === 'Kafka') { -%>
115
- kafkaService.connect().then(() => {
116
- logger.info('Kafka connected');
117
- kafkaService.sendMessage('test-topic', 'Hello Kafka from MVC TS!');
118
- }).catch(err => {
119
- logger.error('Failed to connect to Kafka:', err);
120
- });
111
+ kafkaService.connect()
112
+ .then(async () => {
113
+ logger.info('Kafka connected');
114
+ })
115
+ .catch(err => {
116
+ logger.error('Failed to connect to Kafka after retries:', (err as Error).message);
117
+ });
121
118
  <%_ } -%>
122
119
  });
123
120
 
@@ -126,15 +123,16 @@ const startServer = async () => {
126
123
 
127
124
  <%_ if (database !== 'None') { -%>
128
125
  // Database Sync
126
+ <%_ if (database !== 'None') { -%>
127
+ import <% if (database === 'MongoDB') { %>connectDB<% } else { %>sequelize<% } %> from '@/config/database';
128
+ <%_ } -%>
129
129
  const syncDatabase = async () => {
130
130
  let retries = 30;
131
131
  while (retries) {
132
132
  try {
133
133
  <%_ if (database === 'MongoDB') { -%>
134
- const connectDB = (await import('@/config/database')).default;
135
134
  await connectDB();
136
135
  <%_ } else { -%>
137
- const sequelize = (await import('@/config/database')).default;
138
136
  await sequelize.sync();
139
137
  <%_ } -%>
140
138
  logger.info('Database synced');
@@ -56,7 +56,6 @@ describe('Logger', () => {
56
56
  const winston = require('winston');
57
57
  jest.resetModules();
58
58
  process.env.NODE_ENV = 'production';
59
- // eslint-disable-next-line @typescript-eslint/no-require-imports
60
59
  require('<% if (architecture === "MVC") { %>@/utils/logger<% } else { %>@/infrastructure/log/logger<% } %>');
61
60
  expect(winston.format.json).toHaveBeenCalled();
62
61
  process.env.NODE_ENV = 'test';