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,49 @@
1
+ # ==========================================
2
+ # Stage 1: Builder
3
+ # ==========================================
4
+ FROM node:18-alpine AS builder
5
+
6
+ WORKDIR /app
7
+
8
+ COPY package*.json ./
9
+ COPY tsconfig*.json ./
10
+
11
+ # Install ALL dependencies (including devDeps for build)
12
+ RUN npm ci
13
+
14
+ COPY . .
15
+
16
+ # Build for production
17
+ <% if (language === 'TypeScript') { %>RUN npm run build<% } %>
18
+
19
+ # ==========================================
20
+ # Stage 2: Production
21
+ # ==========================================
22
+ FROM node:18-alpine AS production
23
+
24
+ WORKDIR /app
25
+
26
+ ENV NODE_ENV=production
27
+
28
+ COPY package*.json ./
29
+
30
+ # Install ONLY production dependencies
31
+ RUN npm ci --only=production --ignore-scripts
32
+
33
+ # Copy built artifacts from builder
34
+ <% if (language === 'TypeScript') { %>
35
+ COPY --from=builder /app/dist ./dist
36
+ <% } else { %>
37
+ COPY --from=builder /app/src ./src
38
+ <% } %>
39
+
40
+ # Copy other necessary files (like views if MVC)
41
+ <% if (viewEngine && viewEngine !== 'None') { %>
42
+ COPY --from=builder /app/src/views ./dist/views
43
+ <% } %>
44
+
45
+ EXPOSE 3000
46
+
47
+ USER node
48
+
49
+ CMD ["npm", "start"]
@@ -0,0 +1,87 @@
1
+ # <%= projectName %>
2
+
3
+ ![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)
4
+ ![License](https://img.shields.io/badge/License-ISC-blue.svg)
5
+ <% if (language === 'TypeScript') { %>![TypeScript](https://img.shields.io/badge/Language-TypeScript-blue.svg)<% } else { %>![JavaScript](https://img.shields.io/badge/Language-JavaScript-yellow.svg)<% } %>
6
+
7
+ A production-ready Node.js microservice generated with **<%= architecture %>** and **<%= database %>**.
8
+ This project comes pre-configured with industry-standard tooling for **Code Quality**, **Testing**, and **Security**.
9
+
10
+ ## 🚀 Key Features
11
+
12
+ - **Architecture**: <%= architecture %> (<% if (architecture === 'Clean Architecture') { %>Domain, UseCases, Infrastructure<% } else { %>MVC Pattern<% } %>).
13
+ - **Database**: <%= database %> with **Flyway** migrations.
14
+ - **Security**: Helmet, CORS, Rate Limiting, HPP.
15
+ - **Quality**: Eslint, Prettier, Husky, Lint-Staged.
16
+ - **Testing**: Jest (Unit & Integration).
17
+ - **DevOps**: Multi-stage Docker build, CI/CD ready.
18
+
19
+ ## 🛠️ Getting Started
20
+
21
+ ### 1. Prerequisites
22
+ - Node.js (v18+)
23
+ - Docker & Docker Compose
24
+
25
+ ### 2. Quick Start
26
+ ```bash
27
+ # Install dependencies
28
+ npm install
29
+
30
+ # Setup Git Hooks (Husky)
31
+ npm run prepare
32
+
33
+ # Start Infrastructure (DB, etc.)
34
+ docker-compose up -d
35
+
36
+ # Run Development Server
37
+ npm run dev
38
+ ```
39
+
40
+ ### 3. Development Standards
41
+ Ensure your code meets quality standards before committing:
42
+
43
+ ```bash
44
+ # Run Linter
45
+ npm run lint
46
+
47
+ # Run Tests
48
+ npm test
49
+
50
+ # Format Code
51
+ npm run format
52
+ ```
53
+
54
+ ## 📂 Project Structure
55
+
56
+ The project follows **<%= architecture %>** principles.
57
+ <% if (communication === 'Kafka') { -%>
58
+ Microservices communication handled via **Kafka**.
59
+ <% } else { -%>
60
+ API is exposed via **REST**.
61
+ A Swagger UI for API documentation is available at:
62
+ - **URL**: `http://localhost:3000/api-docs` (Dynamic based on PORT)
63
+ <% } -%>
64
+
65
+ ## 📝 Logging
66
+ This project uses **Winston** for structured logging.
67
+ - **Development**: Logs are printed to the console.
68
+ - **Production**: Logs are saved to files:
69
+ - `error.log`: Only error level logs.
70
+ - `combined.log`: All logs.
71
+
72
+ ## 🐳 Docker Deployment
73
+ This project uses a **Multi-Stage Dockerfile** for optimized production images.
74
+
75
+ ```bash
76
+ # Build Production Image
77
+ docker build -t <%= projectName %> .
78
+
79
+ # Run Container
80
+ docker run -p 3000:3000 -e DATABASE_URL=... <%= projectName %>
81
+ ```
82
+
83
+ ## 🔒 Security Features
84
+ - **Helmet**: Sets secure HTTP headers.
85
+ - **CORS**: Configured for cross-origin requests.
86
+ - **Rate Limiting**: Protects against DDoS / Brute-force.
87
+ - **HPP**: Prevents HTTP Parameter Pollution attacks.
@@ -0,0 +1,5 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ .DS_Store
5
+ coverage
@@ -0,0 +1,20 @@
1
+ const { Sequelize } = require('sequelize');
2
+ require('dotenv').config();
3
+
4
+ // Determine dialect
5
+ <% if (database === 'MySQL') { %>const dialect = 'mysql';<% } -%>
6
+ <% if (database === 'PostgreSQL') { %>const dialect = 'postgres';<% } -%>
7
+
8
+ const sequelize = new Sequelize(
9
+ process.env.DB_NAME || '<%= dbName %>',
10
+ process.env.DB_USER || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
11
+ process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
12
+ {
13
+ host: process.env.DB_HOST || '127.0.0.1',
14
+ dialect: dialect,
15
+ logging: false,
16
+ port: parseInt(process.env.DB_PORT || '<% if (database === 'MySQL') { %>3306<% } else { %>5432<% } %>')
17
+ }
18
+ );
19
+
20
+ module.exports = sequelize;
@@ -0,0 +1,30 @@
1
+ const { DataTypes, Model } = require('sequelize');
2
+ <% if (architecture === 'MVC') { %>const sequelize = require('../config/database');<% } else { %>const sequelize = require('../database');<% } %>
3
+
4
+ class User extends Model {}
5
+
6
+ User.init(
7
+ {
8
+ id: {
9
+ type: DataTypes.INTEGER,
10
+ autoIncrement: true,
11
+ primaryKey: true,
12
+ },
13
+ name: {
14
+ type: DataTypes.STRING,
15
+ allowNull: false,
16
+ },
17
+ email: {
18
+ type: DataTypes.STRING,
19
+ allowNull: false,
20
+ unique: true,
21
+ },
22
+ },
23
+ {
24
+ sequelize,
25
+ tableName: 'users',
26
+ underscored: true,
27
+ }
28
+ );
29
+
30
+ module.exports = User;
@@ -0,0 +1,22 @@
1
+ import { Sequelize } from 'sequelize';
2
+ import dotenv from 'dotenv';
3
+
4
+ dotenv.config();
5
+
6
+ // Determine dialect
7
+ <% if (database === 'MySQL') { %>const dialect = 'mysql';<% } -%>
8
+ <% if (database === 'PostgreSQL') { %>const dialect = 'postgres';<% } -%>
9
+
10
+ const sequelize = new Sequelize(
11
+ process.env.DB_NAME || '<%= dbName %>',
12
+ process.env.DB_USER || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
13
+ process.env.DB_PASSWORD || '<% if (database === 'MySQL') { %>root<% } else { %>postgres<% } %>',
14
+ {
15
+ host: process.env.DB_HOST || '127.0.0.1',
16
+ dialect: dialect,
17
+ logging: false,
18
+ port: parseInt(process.env.DB_PORT || '<% if (database === 'MySQL') { %>3306<% } else { %>5432<% } %>')
19
+ }
20
+ );
21
+
22
+ export default sequelize;
@@ -0,0 +1,34 @@
1
+ import { DataTypes, Model } from 'sequelize';
2
+ <% if (architecture === 'MVC') { %>import sequelize from '../config/database';<% } else { %>import sequelize from '../database';<% } %>
3
+
4
+ class User extends Model {
5
+ public id!: number;
6
+ public name!: string;
7
+ public email!: string;
8
+ }
9
+
10
+ User.init(
11
+ {
12
+ id: {
13
+ type: DataTypes.INTEGER,
14
+ autoIncrement: true,
15
+ primaryKey: true,
16
+ },
17
+ name: {
18
+ type: DataTypes.STRING,
19
+ allowNull: false,
20
+ },
21
+ email: {
22
+ type: DataTypes.STRING,
23
+ allowNull: false,
24
+ unique: true,
25
+ },
26
+ },
27
+ {
28
+ sequelize,
29
+ tableName: 'users',
30
+ underscored: true,
31
+ }
32
+ );
33
+
34
+ export default User;
@@ -0,0 +1,93 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ app:
5
+ build: .
6
+ ports:
7
+ - "${PORT:-3000}:3000"
8
+ depends_on:
9
+ - db
10
+ <% if (communication === 'Kafka') { %> - kafka
11
+ <% } -%>
12
+ <% if (communication === 'Kafka') { %> environment:
13
+ - KAFKA_BROKER=kafka:29092
14
+ - KAFKAJS_NO_PARTITIONER_WARNING=1
15
+ - PORT=3000
16
+ - DB_HOST=db
17
+ <% if (database === 'MySQL') { %> - DB_USER=root
18
+ - DB_PASSWORD=root
19
+ - DB_NAME=<%= dbName %>
20
+ <% } %><% if (database === 'PostgreSQL') { %> - DB_USER=postgres
21
+ - DB_PASSWORD=postgres
22
+ - DB_NAME=<%= dbName %>
23
+ <% } -%>
24
+ <% } else { %>
25
+ environment:
26
+ - PORT=3000
27
+ - DB_HOST=db
28
+ <% if (database === 'MySQL') { %> - DB_USER=root
29
+ - DB_PASSWORD=root
30
+ - DB_NAME=<%= dbName %>
31
+ <% } %><% if (database === 'PostgreSQL') { %> - DB_USER=postgres
32
+ - DB_PASSWORD=postgres
33
+ - DB_NAME=<%= dbName %>
34
+ <% } -%>
35
+ <% } %>
36
+ db:
37
+ <% if (database === 'MySQL') { %> image: mysql:8.0
38
+ command: --default-authentication-plugin=mysql_native_password
39
+ restart: always
40
+ environment:
41
+ MYSQL_ROOT_PASSWORD: root
42
+ MYSQL_DATABASE: <%= dbName %>
43
+ ports:
44
+ - "${DB_PORT:-3306}:3306"
45
+ <% } %><% if (database === 'PostgreSQL') { %> image: postgres:15
46
+ restart: always
47
+ environment:
48
+ POSTGRES_USER: postgres
49
+ POSTGRES_PASSWORD: postgres
50
+ POSTGRES_DB: <%= dbName %>
51
+ ports:
52
+ - "${DB_PORT:-5432}:5432"
53
+ <% } %> volumes:
54
+ - <%= database.toLowerCase() %>_data:/var/lib/<% if (database === 'MySQL') { %>mysql<% } else { %>postgresql/data<% } %>
55
+
56
+ flyway:
57
+ image: flyway/flyway
58
+ command: -connectRetries=60 migrate
59
+ volumes:
60
+ - ./flyway/sql:/flyway/sql
61
+ environment:
62
+ <% if (database === 'MySQL') { %> FLYWAY_URL: jdbc:mysql://db:3306/<%= dbName %>
63
+ FLYWAY_USER: root
64
+ FLYWAY_PASSWORD: root
65
+ <% } %><% if (database === 'PostgreSQL') { %> FLYWAY_URL: jdbc:postgresql://db:5432/<%= dbName %>
66
+ FLYWAY_USER: postgres
67
+ FLYWAY_PASSWORD: postgres
68
+ <% } %> depends_on:
69
+ - db
70
+ <% if (communication === 'Kafka') { %> zookeeper:
71
+ image: confluentinc/cp-zookeeper:7.4.0
72
+ environment:
73
+ ZOOKEEPER_CLIENT_PORT: 2181
74
+ ZOOKEEPER_TICK_TIME: 2000
75
+ ports:
76
+ - "${ZOOKEEPER_PORT:-2181}:2181"
77
+
78
+ kafka:
79
+ image: confluentinc/cp-kafka:7.4.0
80
+ depends_on:
81
+ - zookeeper
82
+ ports:
83
+ - "${KAFKA_PORT:-9092}:9092"
84
+ environment:
85
+ KAFKA_BROKER_ID: 1
86
+ KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
87
+ KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
88
+ KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
89
+ KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
90
+ KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
91
+ <% } -%>
92
+ volumes:
93
+ <%= database.toLowerCase() %>_data:
@@ -0,0 +1,11 @@
1
+ module.exports = {
2
+ testEnvironment: 'node',
3
+ coverageDirectory: 'coverage',
4
+ collectCoverageFrom: ['src/**/*.{js,ts}'],
5
+ testMatch: ['**/*.test.ts', '**/*.test.js'],
6
+ <% if (language === 'TypeScript') { %>preset: 'ts-jest',<% } %>
7
+ coveragePathIgnorePatterns: [
8
+ "/node_modules/",
9
+ "/dist/"
10
+ ]
11
+ };
@@ -0,0 +1,8 @@
1
+ const { Kafka } = require('kafkajs');
2
+
3
+ const kafka = new Kafka({
4
+ clientId: 'nodejs-service',
5
+ brokers: [process.env.KAFKA_BROKER || 'localhost:9092']
6
+ });
7
+
8
+ module.exports = { kafka };
@@ -0,0 +1,29 @@
1
+ const { kafka } = require('../config/kafka');
2
+
3
+ const producer = kafka.producer();
4
+ const consumer = kafka.consumer({ groupId: 'test-group' });
5
+
6
+ const connectKafka = async () => {
7
+ await producer.connect();
8
+ await consumer.connect();
9
+ await consumer.subscribe({ topic: 'test-topic', fromBeginning: true });
10
+
11
+ await consumer.run({
12
+ eachMessage: async ({ topic, partition, message }) => {
13
+ console.log({
14
+ value: message.value.toString(),
15
+ });
16
+ },
17
+ });
18
+ };
19
+
20
+ const sendMessage = async (topic, message) => {
21
+ await producer.send({
22
+ topic,
23
+ messages: [
24
+ { value: message },
25
+ ],
26
+ });
27
+ };
28
+
29
+ module.exports = { connectKafka, sendMessage };
@@ -0,0 +1,6 @@
1
+ import { Kafka } from 'kafkajs';
2
+
3
+ export const kafka = new Kafka({
4
+ clientId: 'nodejs-service',
5
+ brokers: [process.env.KAFKA_BROKER || 'localhost:9092']
6
+ });
@@ -0,0 +1,36 @@
1
+ import { kafka } from '../config/kafka';
2
+ import { EachMessagePayload, Producer, Consumer } from 'kafkajs';
3
+
4
+ export class KafkaService {
5
+ private producer: Producer;
6
+ private consumer: Consumer;
7
+
8
+ constructor() {
9
+ this.producer = kafka.producer();
10
+ this.consumer = kafka.consumer({ groupId: 'test-group' });
11
+ }
12
+
13
+ async connect() {
14
+ await this.producer.connect();
15
+ await this.consumer.connect();
16
+ await this.consumer.subscribe({ topic: 'test-topic', fromBeginning: true });
17
+
18
+ await this.consumer.run({
19
+ eachMessage: async ({ topic, partition, message }: EachMessagePayload) => {
20
+ console.log({
21
+ value: message.value?.toString(),
22
+ });
23
+ },
24
+ });
25
+ }
26
+
27
+ async sendMessage(topic: string, message: string) {
28
+ await this.producer.send({
29
+ topic,
30
+ messages: [
31
+ { value: message },
32
+ ],
33
+ });
34
+ }
35
+ }
36
+
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "<%= projectName %>",
3
+ "version": "1.0.0",
4
+ "description": "Generated by nodejs-quickstart",
5
+ "main": "<% if (language === 'TypeScript') { %>dist/index.js<% } else { %>src/index.js<% } %>",
6
+ "scripts": {
7
+ "start": "<% if (language === 'TypeScript') { %>node dist/index.js<% } else { %>node src/index.js<% } %>",
8
+ "dev": "<% if (language === 'TypeScript') { %>nodemon --exec ts-node src/index.ts<% } else { %>nodemon src/index.js<% } %>"<% if (language === 'TypeScript') { %>,
9
+ "build": "rimraf dist && tsc<% if (viewEngine && viewEngine !== 'None') { %> && copyfiles -u 1 \"src/views/**/*\" dist/<% } %>"<% } %>,
10
+ "lint": "eslint . --ext .ts,.js",
11
+ "lint:fix": "eslint . --ext .ts,.js --fix",
12
+ "format": "prettier --write .",
13
+ "prepare": "husky install",
14
+ "test": "jest",
15
+ "test:watch": "jest --watch",
16
+ "test:coverage": "jest --coverage"
17
+ },
18
+ "dependencies": {
19
+ "express": "^4.18.2",
20
+ "dotenv": "^16.3.1",
21
+ <% if (database === 'MySQL') { %> "mysql2": "^3.6.5",
22
+ <% } -%>
23
+ <% if (database === 'PostgreSQL') { %> "pg": "^8.11.3",
24
+ <% } -%>
25
+ "sequelize": "^6.35.2",
26
+ <% if (communication === 'Kafka') { %> "kafkajs": "^2.2.4",
27
+ <% } -%>
28
+ <% if (viewEngine === 'EJS') { %> "ejs": "^3.1.9",
29
+ <% } -%>
30
+ <% if (viewEngine === 'Pug') { %> "pug": "^3.0.2",
31
+ <% } -%>
32
+ "cors": "^2.8.5",
33
+ "helmet": "^7.1.0",
34
+ "hpp": "^0.2.3",
35
+ "express-rate-limit": "^7.1.5",
36
+ "winston": "^3.11.0"<% if (communication === 'REST APIs') { %>,
37
+ "swagger-ui-express": "^5.0.0",
38
+ "swagger-jsdoc": "^6.2.8"
39
+ <% } %>
40
+ },
41
+ "devDependencies": {
42
+ "nodemon": "^3.0.2"<% if (language === 'TypeScript') { %>,
43
+ "typescript": "^5.3.3",
44
+ "ts-node": "^10.9.2",
45
+ "@types/node": "^20.10.5",
46
+ "@types/express": "^4.17.21",
47
+ "@types/cors": "^2.8.17",
48
+ "@types/dotenv": "^8.2.0",
49
+ "@types/hpp": "^0.2.3",
50
+ <% if (database === 'PostgreSQL') { %> "@types/pg": "^8.10.9",
51
+ <% } -%>
52
+ "@types/sequelize": "^4.28.19",
53
+ "rimraf": "^5.0.5"<% if (viewEngine && viewEngine !== 'None') { %>,
54
+ "copyfiles": "^2.4.1"<% } %><% } %>,
55
+ "eslint": "^8.56.0",
56
+ "prettier": "^3.1.1",
57
+ "eslint-config-prettier": "^9.1.0",
58
+ "husky": "^8.0.3",
59
+ "lint-staged": "^15.2.0"<% if (language === 'TypeScript') { %>,
60
+ "@typescript-eslint/eslint-plugin": "^6.18.1",
61
+ "@typescript-eslint/parser": "^6.18.1",
62
+ <% if (communication === 'REST APIs') { %> "@types/swagger-ui-express": "^4.1.6",
63
+ "@types/swagger-jsdoc": "^6.0.4",<% } -%>
64
+ "jest": "^29.7.0",
65
+ "ts-jest": "^29.1.1",
66
+ "@types/jest": "^29.5.11",
67
+ "supertest": "^6.3.3",
68
+ "@types/supertest": "^6.0.2"<% } else { %>,
69
+ "jest": "^29.7.0",
70
+ "supertest": "^6.3.3"<% } %>
71
+ },
72
+ "lint-staged": {
73
+ "*.{js,ts}": [
74
+ "eslint --fix",
75
+ "prettier --write"
76
+ ]
77
+ }
78
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "rootDir": "./src",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true
11
+ },
12
+ "include": [
13
+ "src/**/*"
14
+ ],
15
+ "exclude": [
16
+ "node_modules",
17
+ "**/*.test.ts"
18
+ ]
19
+ }
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title><%= projectName %></title>
7
+ <style>
8
+ body { font-family: sans-serif; padding: 20px; }
9
+ h1 { color: #333; }
10
+ .status { margin-top: 20px; padding: 10px; background: #e0f7fa; border-left: 5px solid #00acc1; }
11
+ </style>
12
+ </head>
13
+ <body>
14
+ <h1>Welcome to <%= projectName %></h1>
15
+ <p>Architecture: <strong><%= architecture %></strong></p>
16
+ <p>Database: <strong><%= database %></strong></p>
17
+
18
+ <% if (communication === 'Kafka') { %>
19
+ <div class="status">
20
+ <h3>Kafka Status</h3>
21
+ <p>Connected to Kafka Broker.</p>
22
+ <p>Check console for messages.</p>
23
+ </div>
24
+ <% } else { %>
25
+ <div class="status">
26
+ <h3>API Status</h3>
27
+ <p>REST API is active.</p>
28
+ </div>
29
+ <% } %>
30
+ </body>
31
+ </html>
@@ -0,0 +1,26 @@
1
+ doctype html
2
+ html(lang="en")
3
+ head
4
+ meta(charset="UTF-8")
5
+ meta(name="viewport", content="width=device-width, initial-scale=1.0")
6
+ title= projectName
7
+ style.
8
+ body { font-family: sans-serif; padding: 20px; }
9
+ h1 { color: #333; }
10
+ .status { margin-top: 20px; padding: 10px; background: #e0f7fa; border-left: 5px solid #00acc1; }
11
+ body
12
+ h1 Welcome to #{projectName}
13
+ p Architecture:
14
+ strong #{architecture}
15
+ p Database:
16
+ strong #{database}
17
+
18
+ if communication === 'Kafka'
19
+ .status
20
+ h3 Kafka Status
21
+ p Connected to Kafka Broker.
22
+ p Check console for messages.
23
+ else
24
+ .status
25
+ h3 API Status
26
+ p REST API is active.
@@ -0,0 +1,9 @@
1
+ CREATE TABLE users (
2
+ id INT AUTO_INCREMENT PRIMARY KEY,
3
+ name VARCHAR(255) NOT NULL,
4
+ email VARCHAR(255) NOT NULL UNIQUE,
5
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
6
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
7
+ );
8
+
9
+ INSERT INTO users (name, email) VALUES ('Admin User', 'admin@example.com');
@@ -0,0 +1,9 @@
1
+ CREATE TABLE users (
2
+ id SERIAL PRIMARY KEY,
3
+ name VARCHAR(255) NOT NULL,
4
+ email VARCHAR(255) NOT NULL UNIQUE,
5
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
6
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
7
+ );
8
+
9
+ INSERT INTO users (name, email) VALUES ('Admin User', 'admin@example.com');
@@ -0,0 +1,12 @@
1
+ // Database configuration placeholder
2
+ // Use environment variables from .env depending on your DB choice (MySQL/Postgres)
3
+ require('dotenv').config();
4
+
5
+ const dbConfig = {
6
+ host: process.env.DB_HOST,
7
+ user: process.env.DB_USER,
8
+ password: process.env.DB_PASSWORD,
9
+ database: process.env.DB_NAME
10
+ };
11
+
12
+ module.exports = dbConfig;
@@ -0,0 +1,23 @@
1
+ const swaggerJsdoc = require('swagger-jsdoc');
2
+
3
+ const options = {
4
+ definition: {
5
+ openapi: '3.0.0',
6
+ info: {
7
+ title: 'NodeJS API Service',
8
+ version: '1.0.0',
9
+ description: 'API documentation for the NodeJS Service',
10
+ },
11
+ servers: [
12
+ {
13
+ url: process.env.SERVER_URL || `http://localhost:${process.env.PORT || 3000}`,
14
+ description: 'Server',
15
+ },
16
+ ],
17
+ },
18
+ apis: ['./src/routes/*.js'], // Path to the API docs
19
+ };
20
+
21
+ const specs = swaggerJsdoc(options);
22
+
23
+ module.exports = specs;
@@ -0,0 +1,14 @@
1
+ exports.getUsers = (req, res) => {
2
+ res.json([
3
+ { id: 1, name: 'John Doe' },
4
+ { id: 2, name: 'Jane Doe' }
5
+ ]);
6
+ };
7
+
8
+ exports.createUser = (req, res) => {
9
+ const { name, email } = req.body;
10
+ res.status(201).json({
11
+ message: 'User created successfully',
12
+ user: { name, email }
13
+ });
14
+ };