nodejs-quickstart-structure 1.1.6

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 (65) hide show
  1. package/README.md +98 -0
  2. package/bin/index.js +66 -0
  3. package/docs/demo.gif +0 -0
  4. package/docs/generateCase.md +58 -0
  5. package/lib/generator.js +315 -0
  6. package/lib/prompts.js +76 -0
  7. package/package.json +40 -0
  8. package/templates/clean-architecture/js/src/domain/models/User.js +9 -0
  9. package/templates/clean-architecture/js/src/domain/repositories/UserRepository.js +9 -0
  10. package/templates/clean-architecture/js/src/index.js.ejs +37 -0
  11. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +22 -0
  12. package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +19 -0
  13. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +31 -0
  14. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js +23 -0
  15. package/templates/clean-architecture/js/src/interfaces/controllers/UserController.js +30 -0
  16. package/templates/clean-architecture/js/src/interfaces/routes/api.js +77 -0
  17. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -0
  18. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -0
  19. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -0
  20. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +24 -0
  21. package/templates/clean-architecture/ts/src/domain/user.ts +7 -0
  22. package/templates/clean-architecture/ts/src/index.ts.ejs +71 -0
  23. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +22 -0
  24. package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.ts.ejs +18 -0
  25. package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts +45 -0
  26. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +76 -0
  27. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -0
  28. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -0
  29. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -0
  30. package/templates/common/.dockerignore +10 -0
  31. package/templates/common/.eslintrc.json.ejs +26 -0
  32. package/templates/common/.lintstagedrc +6 -0
  33. package/templates/common/Dockerfile +49 -0
  34. package/templates/common/README.md.ejs +87 -0
  35. package/templates/common/_gitignore +5 -0
  36. package/templates/common/database/js/database.js.ejs +20 -0
  37. package/templates/common/database/js/models/User.js.ejs +30 -0
  38. package/templates/common/database/ts/database.ts.ejs +22 -0
  39. package/templates/common/database/ts/models/User.ts.ejs +34 -0
  40. package/templates/common/docker-compose.yml.ejs +93 -0
  41. package/templates/common/jest.config.js.ejs +11 -0
  42. package/templates/common/kafka/js/config/kafka.js +8 -0
  43. package/templates/common/kafka/js/services/kafkaService.js +29 -0
  44. package/templates/common/kafka/ts/config/kafka.ts +6 -0
  45. package/templates/common/kafka/ts/services/kafkaService.ts +36 -0
  46. package/templates/common/package.json.ejs +78 -0
  47. package/templates/common/tsconfig.json +19 -0
  48. package/templates/common/views/ejs/index.ejs +31 -0
  49. package/templates/common/views/pug/index.pug +26 -0
  50. package/templates/db/mysql/V1__Initial_Setup.sql +9 -0
  51. package/templates/db/postgres/V1__Initial_Setup.sql +9 -0
  52. package/templates/mvc/js/src/config/database.js +12 -0
  53. package/templates/mvc/js/src/config/swagger.js +23 -0
  54. package/templates/mvc/js/src/controllers/userController.js +14 -0
  55. package/templates/mvc/js/src/controllers/userController.js.ejs +23 -0
  56. package/templates/mvc/js/src/index.js.ejs +81 -0
  57. package/templates/mvc/js/src/routes/api.js +74 -0
  58. package/templates/mvc/js/src/utils/httpCodes.js +9 -0
  59. package/templates/mvc/js/src/utils/logger.js +30 -0
  60. package/templates/mvc/ts/src/config/swagger.ts.ejs +24 -0
  61. package/templates/mvc/ts/src/controllers/userController.ts.ejs +32 -0
  62. package/templates/mvc/ts/src/index.ts.ejs +89 -0
  63. package/templates/mvc/ts/src/routes/api.ts +76 -0
  64. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -0
  65. package/templates/mvc/ts/src/utils/logger.ts +22 -0
@@ -0,0 +1,23 @@
1
+ const User = require('../models/User');
2
+ const HTTP_STATUS = require('../utils/httpCodes');
3
+
4
+ const getUsers = async (req, res) => {
5
+ try {
6
+ const users = await User.findAll();
7
+ res.json(users);
8
+ } catch (error) {
9
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
10
+ }
11
+ };
12
+
13
+ const createUser = async (req, res) => {
14
+ try {
15
+ const { name, email } = req.body;
16
+ const user = await User.create({ name, email });
17
+ res.status(HTTP_STATUS.CREATED).json(user);
18
+ } catch (error) {
19
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
20
+ }
21
+ };
22
+
23
+ module.exports = { getUsers, createUser };
@@ -0,0 +1,81 @@
1
+ const express = require('express');
2
+ const cors = require('cors');
3
+ require('dotenv').config();
4
+ <% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { %>const apiRoutes = require('./routes/api');<% } %>
5
+ <% if (communication === 'Kafka') { %>const { connectKafka, sendMessage } = require('./services/kafkaService');<% } %>
6
+ <% if (communication === 'REST APIs') { %>
7
+ const swaggerUi = require('swagger-ui-express');
8
+ const swaggerSpecs = require('./config/swagger');
9
+ <% } %>
10
+
11
+ const app = express();
12
+ const PORT = process.env.PORT || 3000;
13
+ const logger = require('./utils/logger');
14
+
15
+ app.use(cors());
16
+ app.use(express.json());
17
+
18
+ <% if (communication === 'REST APIs') { %>
19
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
20
+ <% } %>
21
+
22
+ <% if (viewEngine === 'EJS' || viewEngine === 'Pug') { %>
23
+ // View Engine Setup
24
+ const path = require('path');
25
+ app.set('views', path.join(__dirname, 'views'));
26
+ app.set('view engine', '<%= viewEngine.toLowerCase() %>');
27
+ <% } -%>
28
+
29
+ // Routes
30
+ <% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { -%>
31
+ app.use('/api', apiRoutes);
32
+ <% } -%>
33
+ <% if (viewEngine && viewEngine !== 'None') { -%>
34
+ app.get('/', (req, res) => {
35
+ res.render('index', {
36
+ projectName: 'NodeJS Service',
37
+ architecture: 'MVC',
38
+ database: '<%= database %>',
39
+ communication: '<%= communication %>'
40
+ });
41
+ });
42
+ <% } -%>
43
+
44
+ app.get('/health', (req, res) => {
45
+ res.json({ status: 'UP' });
46
+ });
47
+
48
+ // Database Sync
49
+ const syncDatabase = async () => {
50
+ let retries = 30;
51
+ while (retries) {
52
+ try {
53
+ const sequelize = require('./config/database');
54
+ await sequelize.sync();
55
+ logger.info('Database synced');
56
+
57
+ // Start Server after DB is ready
58
+ app.listen(PORT, async () => {
59
+ logger.info(`Server running on port ${PORT}`);
60
+ <% if (communication === 'Kafka') { %>
61
+ try {
62
+ await connectKafka();
63
+ logger.info('Kafka connected');
64
+ // Demo: Send a test message
65
+ await sendMessage('test-topic', 'Hello Kafka from MVC JS!');
66
+ } catch (err) {
67
+ logger.error('Failed to connect to Kafka:', err);
68
+ }
69
+ <% } -%>
70
+ });
71
+ break;
72
+ } catch (err) {
73
+ logger.error('Database sync failed:', err);
74
+ retries -= 1;
75
+ logger.info(`Retries left: ${retries}. Waiting 5s...`);
76
+ await new Promise(res => setTimeout(res, 5000));
77
+ }
78
+ }
79
+ };
80
+
81
+ syncDatabase();
@@ -0,0 +1,74 @@
1
+ const express = require('express');
2
+ const router = express.Router();
3
+ const userController = require('../controllers/userController');
4
+
5
+ /**
6
+ * @swagger
7
+ * components:
8
+ * schemas:
9
+ * User:
10
+ * type: object
11
+ * required:
12
+ * - name
13
+ * - email
14
+ * properties:
15
+ * id:
16
+ * type: integer
17
+ * description: The auto-generated id of the user
18
+ * name:
19
+ * type: string
20
+ * description: The name of the user
21
+ * email:
22
+ * type: string
23
+ * description: The email of the user
24
+ * example:
25
+ * id: 1
26
+ * name: John Doe
27
+ * email: john@example.com
28
+ */
29
+
30
+ /**
31
+ * @swagger
32
+ * tags:
33
+ * name: Users
34
+ * description: The users managing API
35
+ */
36
+
37
+ /**
38
+ * @swagger
39
+ * /api/users:
40
+ * get:
41
+ * summary: Returns the list of all the users
42
+ * tags: [Users]
43
+ * responses:
44
+ * 200:
45
+ * description: The list of the users
46
+ * content:
47
+ * application/json:
48
+ * schema:
49
+ * type: array
50
+ * items:
51
+ * $ref: '#/components/schemas/User'
52
+ * post:
53
+ * summary: Create a new user
54
+ * tags: [Users]
55
+ * requestBody:
56
+ * required: true
57
+ * content:
58
+ * application/json:
59
+ * schema:
60
+ * $ref: '#/components/schemas/User'
61
+ * responses:
62
+ * 201:
63
+ * description: The created user.
64
+ * content:
65
+ * application/json:
66
+ * schema:
67
+ * $ref: '#/components/schemas/User'
68
+ * 500:
69
+ * description: Some server error
70
+ */
71
+ router.get('/users', userController.getUsers);
72
+ router.post('/users', userController.createUser);
73
+
74
+ module.exports = router;
@@ -0,0 +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;
@@ -0,0 +1,30 @@
1
+ const winston = require('winston');
2
+
3
+ const logger = winston.createLogger({
4
+ level: 'info',
5
+ format: winston.format.combine(
6
+ winston.format.timestamp(),
7
+ winston.format.json()
8
+ ),
9
+ defaultMeta: { service: 'user-service' },
10
+ transports: [
11
+ //
12
+ // - Write all logs with importance level of `error` or less to `error.log`
13
+ // - Write all logs with importance level of `info` or less to `combined.log`
14
+ //
15
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
16
+ new winston.transports.File({ filename: 'combined.log' }),
17
+ ],
18
+ });
19
+
20
+ //
21
+ // If we're not in production then log to the `console` with the format:
22
+ // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
23
+ //
24
+ if (process.env.NODE_ENV !== 'production') {
25
+ logger.add(new winston.transports.Console({
26
+ format: winston.format.simple(),
27
+ }));
28
+ }
29
+
30
+ module.exports = logger;
@@ -0,0 +1,24 @@
1
+ <% if (communication === 'REST APIs') { %>
2
+ import swaggerJsdoc from 'swagger-jsdoc';
3
+
4
+ const options = {
5
+ definition: {
6
+ openapi: '3.0.0',
7
+ info: {
8
+ title: 'NodeJS API Service',
9
+ version: '1.0.0',
10
+ description: 'API documentation for the NodeJS Service',
11
+ },
12
+ servers: [
13
+ {
14
+ url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
15
+ description: 'Server',
16
+ },
17
+ ],
18
+ },
19
+ apis: ['./src/routes/*.ts', './dist/routes/*.js'], // Path to the API docs
20
+ };
21
+
22
+ const specs = swaggerJsdoc(options);
23
+
24
+ export default specs;<% } %>
@@ -0,0 +1,32 @@
1
+ import { Request, Response } from 'express';
2
+ import User from '../models/User';
3
+ import { HTTP_STATUS } from '../utils/httpCodes';
4
+
5
+ export class UserController {
6
+ async getUsers(req: Request, res: Response) {
7
+ try {
8
+ const users = await User.findAll();
9
+ res.json(users);
10
+ } catch (error) {
11
+ if (error instanceof Error) {
12
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
13
+ } else {
14
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: 'Unknown error occurred' });
15
+ }
16
+ }
17
+ }
18
+
19
+ async createUser(req: Request, res: Response) {
20
+ try {
21
+ const { name, email } = req.body;
22
+ const user = await User.create({ name, email });
23
+ res.status(HTTP_STATUS.CREATED).json(user);
24
+ } catch (error) {
25
+ if (error instanceof Error) {
26
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
27
+ } else {
28
+ res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: 'Unknown error occurred' });
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,89 @@
1
+ import express, { Request, Response } from 'express';
2
+ import cors from 'cors';
3
+ import helmet from 'helmet';
4
+ import hpp from 'hpp';
5
+ import rateLimit from 'express-rate-limit';
6
+ import dotenv from 'dotenv';
7
+ import logger from './utils/logger';
8
+ <% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { %>import apiRoutes from './routes/api';<% } %>
9
+ <% if (communication === 'REST APIs') { %>
10
+ import swaggerUi from 'swagger-ui-express';
11
+ import swaggerSpecs from './config/swagger';<% } %>
12
+ <% if (communication === 'Kafka') { %>import { KafkaService } from './services/kafkaService';<% } %>
13
+
14
+ dotenv.config();
15
+
16
+ const app = express();
17
+ const port = process.env.PORT || 3000;
18
+
19
+ // Security Middleware
20
+ app.use(helmet());
21
+ app.use(hpp());
22
+ app.use(cors({ origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE'] }));
23
+ const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 100 });
24
+ app.use(limiter);
25
+
26
+ app.use(express.json());
27
+
28
+ <% if (communication === 'REST APIs') { %>
29
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));<% } %>
30
+
31
+ <% if (viewEngine === 'EJS' || viewEngine === 'Pug') { %>
32
+ // View Engine Setup
33
+ import path from 'path';
34
+ app.set('views', path.join(__dirname, 'views'));
35
+ app.set('view engine', '<%= viewEngine.toLowerCase() %>');<% } -%>
36
+
37
+ // Routes
38
+ <% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { -%>
39
+ app.use('/api', apiRoutes);<% } -%>
40
+ <% if (viewEngine && viewEngine !== 'None') { -%>
41
+ app.get('/', (req: Request, res: Response) => {
42
+ res.render('index', {
43
+ projectName: 'NodeJS Service',
44
+ architecture: 'MVC',
45
+ database: '<%= database %>',
46
+ communication: '<%= communication %>'
47
+ });
48
+ });
49
+ <% } -%>
50
+
51
+ app.get('/health', (req: Request, res: Response) => {
52
+ res.json({ status: 'UP' });
53
+ });
54
+
55
+ // Database Sync
56
+ const syncDatabase = async () => {
57
+ let retries = 30;
58
+ while (retries) {
59
+ try {
60
+ const sequelize = (await import('./config/database')).default;
61
+ await sequelize.sync();
62
+ logger.info('Database synced');
63
+
64
+ // Start Server after DB is ready
65
+ app.listen(port, async () => {
66
+ logger.info(`Server running on port ${port}`);
67
+ <% if (communication === 'Kafka') { %>
68
+ try {
69
+ const kafkaService = new KafkaService();
70
+ await kafkaService.connect();
71
+ logger.info('Kafka connected');
72
+ // Demo: Send a test message
73
+ await kafkaService.sendMessage('test-topic', 'Hello Kafka from MVC TS!');
74
+ } catch (err) {
75
+ logger.error('Failed to connect to Kafka:', err);
76
+ }
77
+ <% } -%>
78
+ });
79
+ break;
80
+ } catch (err) {
81
+ logger.error('Database sync failed:', err);
82
+ retries -= 1;
83
+ logger.info(`Retries left: ${retries}. Waiting 5s...`);
84
+ await new Promise(res => setTimeout(res, 5000));
85
+ }
86
+ }
87
+ };
88
+
89
+ syncDatabase();
@@ -0,0 +1,76 @@
1
+ import { Router, Request, Response } from 'express';
2
+ import { UserController } from '../controllers/userController';
3
+
4
+ const router = Router();
5
+ const userController = new UserController();
6
+
7
+ /**
8
+ * @swagger
9
+ * components:
10
+ * schemas:
11
+ * User:
12
+ * type: object
13
+ * required:
14
+ * - name
15
+ * - email
16
+ * properties:
17
+ * id:
18
+ * type: integer
19
+ * description: The auto-generated id of the user
20
+ * name:
21
+ * type: string
22
+ * description: The name of the user
23
+ * email:
24
+ * type: string
25
+ * description: The email of the user
26
+ * example:
27
+ * id: 1
28
+ * name: John Doe
29
+ * email: john@example.com
30
+ */
31
+
32
+ /**
33
+ * @swagger
34
+ * tags:
35
+ * name: Users
36
+ * description: The users managing API
37
+ */
38
+
39
+ /**
40
+ * @swagger
41
+ * /api/users:
42
+ * get:
43
+ * summary: Returns the list of all the users
44
+ * tags: [Users]
45
+ * responses:
46
+ * 200:
47
+ * description: The list of the users
48
+ * content:
49
+ * application/json:
50
+ * schema:
51
+ * type: array
52
+ * items:
53
+ * $ref: '#/components/schemas/User'
54
+ * post:
55
+ * summary: Create a new user
56
+ * tags: [Users]
57
+ * requestBody:
58
+ * required: true
59
+ * content:
60
+ * application/json:
61
+ * schema:
62
+ * $ref: '#/components/schemas/User'
63
+ * responses:
64
+ * 201:
65
+ * description: The created user.
66
+ * content:
67
+ * application/json:
68
+ * schema:
69
+ * $ref: '#/components/schemas/User'
70
+ * 500:
71
+ * description: Some server error
72
+ */
73
+ router.get('/users', (req: Request, res: Response) => userController.getUsers(req, res));
74
+ router.post('/users', (req: Request, res: Response) => userController.createUser(req, res));
75
+
76
+ export default router;
@@ -0,0 +1,7 @@
1
+ export const HTTP_STATUS = {
2
+ OK: 200,
3
+ CREATED: 201,
4
+ BAD_REQUEST: 400,
5
+ NOT_FOUND: 404,
6
+ INTERNAL_SERVER_ERROR: 500
7
+ } as const;
@@ -0,0 +1,22 @@
1
+ import winston from 'winston';
2
+
3
+ const logger = winston.createLogger({
4
+ level: 'info',
5
+ format: winston.format.combine(
6
+ winston.format.timestamp(),
7
+ winston.format.json()
8
+ ),
9
+ defaultMeta: { service: 'user-service' },
10
+ transports: [
11
+ new winston.transports.File({ filename: 'error.log', level: 'error' }),
12
+ new winston.transports.File({ filename: 'combined.log' }),
13
+ ],
14
+ });
15
+
16
+ if (process.env.NODE_ENV !== 'production') {
17
+ logger.add(new winston.transports.Console({
18
+ format: winston.format.simple(),
19
+ }));
20
+ }
21
+
22
+ export default logger;