nodejs-structure-cli 1.0.1 → 1.0.3
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/bin/index.js +5 -5
- package/lib/generator.js +1 -3
- package/package.json +1 -1
- package/templates/clean-architecture/js/src/domain/models/User.js.ejs +1 -1
- package/templates/clean-architecture/js/src/errors/ApiError.js +1 -1
- package/templates/clean-architecture/js/src/errors/BadRequestError.js +4 -4
- package/templates/clean-architecture/js/src/errors/NotFoundError.js +4 -4
- package/templates/clean-architecture/js/src/index.js.ejs +6 -8
- package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +5 -6
- package/templates/clean-architecture/js/src/infrastructure/log/logger.js +3 -3
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +2 -2
- package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +4 -4
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +28 -21
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +7 -3
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +12 -12
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +13 -15
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +2 -2
- package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +4 -4
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +3 -3
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +2 -2
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +3 -3
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +1 -3
- package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +6 -6
- package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +2 -2
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js +1 -1
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +1 -1
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +5 -5
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +1 -1
- package/templates/clean-architecture/js/src/utils/errorMessages.js +1 -1
- package/templates/clean-architecture/js/src/utils/httpCodes.js +1 -1
- package/templates/common/SECURITY.md +18 -0
- package/templates/common/caching/clean/js/CreateUser.js.ejs +5 -5
- package/templates/common/caching/clean/js/DeleteUser.js.ejs +4 -4
- package/templates/common/caching/clean/js/GetAllUsers.js.ejs +4 -4
- package/templates/common/caching/clean/js/UpdateUser.js.ejs +4 -4
- package/templates/common/caching/js/memoryCache.js.ejs +3 -3
- package/templates/common/caching/js/redisClient.js.ejs +6 -4
- package/templates/common/database/js/database.js.ejs +5 -3
- package/templates/common/database/js/models/User.js.ejs +4 -4
- package/templates/common/database/js/mongoose.js.ejs +6 -4
- package/templates/common/ecosystem.config.js.ejs +1 -1
- package/templates/common/health/js/healthRoute.js.ejs +11 -8
- package/templates/common/health/js/healthRoute.spec.js.ejs +10 -9
- package/templates/common/jest.config.js.ejs +1 -1
- package/templates/common/jest.e2e.config.js.ejs +4 -3
- package/templates/common/kafka/js/config/kafka.js +3 -3
- package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +2 -2
- package/templates/common/kafka/js/messaging/userEventSchema.js.ejs +3 -3
- package/templates/common/kafka/js/messaging/welcomeEmailConsumer.js.ejs +6 -6
- package/templates/common/kafka/js/services/kafkaService.js.ejs +5 -7
- package/templates/common/kafka/js/utils/kafkaEvents.js.ejs +1 -3
- package/templates/common/migrate-mongo-config.js.ejs +2 -2
- package/templates/common/migrations/init.js.ejs +18 -20
- package/templates/common/package.json.ejs +1 -0
- package/templates/common/scripts/run-e2e.js.ejs +6 -3
- package/templates/common/shutdown/js/gracefulShutdown.js.ejs +23 -14
- package/templates/common/src/config/auth.js.ejs +1 -1
- package/templates/common/src/controllers/authController.js.ejs +2 -2
- package/templates/common/src/dummy.ts +3 -0
- package/templates/common/src/middleware/auth.js.ejs +1 -1
- package/templates/common/src/middleware/upload.js.ejs +1 -1
- package/templates/common/src/routes/authRoutes.js.ejs +1 -1
- package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +1 -1
- package/templates/common/src/utils/errorMiddleware.spec.js.ejs +5 -6
- package/templates/common/tsconfig.json +2 -1
- package/templates/mvc/js/src/config/env.js.ejs +5 -4
- package/templates/mvc/js/src/config/swagger.js.ejs +7 -3
- package/templates/mvc/js/src/controllers/userController.js.ejs +17 -21
- package/templates/mvc/js/src/controllers/userController.spec.js.ejs +12 -12
- package/templates/mvc/js/src/errors/ApiError.js +1 -1
- package/templates/mvc/js/src/errors/BadRequestError.js +4 -4
- package/templates/mvc/js/src/errors/BadRequestError.spec.js.ejs +4 -4
- package/templates/mvc/js/src/errors/NotFoundError.js +4 -4
- package/templates/mvc/js/src/errors/NotFoundError.spec.js.ejs +4 -4
- package/templates/mvc/js/src/graphql/context.js.ejs +1 -1
- package/templates/mvc/js/src/graphql/index.js.ejs +4 -4
- package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +3 -3
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +2 -2
- package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +3 -3
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +2 -2
- package/templates/mvc/js/src/index.js.ejs +26 -25
- package/templates/mvc/js/src/routes/api.js.ejs +7 -6
- package/templates/mvc/js/src/routes/api.spec.js.ejs +4 -4
- package/templates/mvc/js/src/utils/errorMessages.js +1 -1
- package/templates/mvc/js/src/utils/errorMiddleware.js +4 -4
- package/templates/mvc/js/src/utils/httpCodes.js +1 -1
- package/templates/mvc/js/src/utils/logger.js +3 -3
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
<%_ if (caching === 'Redis') { -%>
|
|
2
|
-
|
|
2
|
+
import cacheService from '../infrastructure/caching/redisClient.js';
|
|
3
3
|
<%_ } else if (caching === 'Memory Cache') { -%>
|
|
4
|
-
|
|
4
|
+
import cacheService from '../infrastructure/caching/memoryCache.js';
|
|
5
5
|
<%_ } -%>
|
|
6
|
-
|
|
6
|
+
import logger from '../infrastructure/log/logger.js';
|
|
7
7
|
|
|
8
8
|
class UpdateUser {
|
|
9
9
|
constructor(userRepository) {
|
|
@@ -24,4 +24,4 @@ class UpdateUser {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
export default UpdateUser;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import NodeCache from 'node-cache';
|
|
2
|
+
import logger from '<%- loggerPath %>.js';
|
|
3
3
|
|
|
4
4
|
class MemoryCacheService {
|
|
5
5
|
constructor() {
|
|
@@ -57,4 +57,4 @@ class MemoryCacheService {
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
|
|
60
|
+
export default MemoryCacheService.getInstance();
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import Redis from 'ioredis';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import logger from '<%- loggerPath %>.js';
|
|
4
|
+
|
|
5
|
+
dotenv.config();
|
|
4
6
|
|
|
5
7
|
class RedisService {
|
|
6
8
|
constructor() {
|
|
@@ -72,4 +74,4 @@ class RedisService {
|
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
export default RedisService.getInstance();
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Sequelize } from 'sequelize';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
|
|
4
|
+
dotenv.config();
|
|
3
5
|
|
|
4
6
|
<% if (database === 'MySQL') { %>const dialect = 'mysql';<% } -%>
|
|
5
7
|
<% if (database === 'PostgreSQL') { %>const dialect = 'postgres';<% } -%>
|
|
@@ -16,4 +18,4 @@ const sequelize = new Sequelize(
|
|
|
16
18
|
}
|
|
17
19
|
);
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
export default sequelize;
|
|
@@ -39,10 +39,10 @@ class UserModel {
|
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
export default UserModel;
|
|
43
43
|
<% } else { -%>
|
|
44
|
-
|
|
45
|
-
<% if (architecture === 'MVC') { %>
|
|
44
|
+
import { DataTypes, Model } from 'sequelize';
|
|
45
|
+
<% if (architecture === 'MVC') { %>import sequelize from '../config/database.js';<% } else { %>import sequelize from '../database.js';<% } %>
|
|
46
46
|
|
|
47
47
|
class User extends Model {}
|
|
48
48
|
|
|
@@ -87,5 +87,5 @@ User.init(
|
|
|
87
87
|
}
|
|
88
88
|
);
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
export default User;
|
|
91
91
|
<% } -%>
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import mongoose from 'mongoose';
|
|
2
2
|
|
|
3
3
|
let logger;
|
|
4
4
|
<% if (architecture === 'MVC') { %>
|
|
5
|
-
|
|
5
|
+
import logger_mvc from '../utils/logger.js';
|
|
6
|
+
logger = logger_mvc;
|
|
6
7
|
<% } else { %>
|
|
7
|
-
|
|
8
|
+
import logger_ca from '../log/logger.js';
|
|
9
|
+
logger = logger_ca;
|
|
8
10
|
<% } %>
|
|
9
11
|
const connectDB = async () => {
|
|
10
12
|
const dbHost = process.env.DB_HOST || 'localhost';
|
|
@@ -30,4 +32,4 @@ const connectDB = async () => {
|
|
|
30
32
|
}
|
|
31
33
|
};
|
|
32
34
|
|
|
33
|
-
|
|
35
|
+
export default connectDB; // Export function to call in index.js
|
|
@@ -1,16 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import logger from '<% if (architecture === "MVC") { %>../utils/logger.js<% } else { %>../../infrastructure/log/logger.js<% } %>';
|
|
3
|
+
import HTTP_STATUS from '<% if (architecture === "MVC") { %>../utils/httpCodes.js<% } else { %>../../utils/httpCodes.js<% } %>';
|
|
4
|
+
|
|
5
5
|
<%_ if (database !== 'None') { -%>
|
|
6
|
-
|
|
6
|
+
import ERROR_MESSAGES from '<% if (architecture === "MVC") { %>../utils/errorMessages.js<% } else { %>../../utils/errorMessages.js<% } %>';
|
|
7
7
|
<%_ } -%>
|
|
8
|
+
|
|
8
9
|
<%_ if (database === 'MongoDB') { -%>
|
|
9
|
-
|
|
10
|
+
import mongoose from 'mongoose';
|
|
10
11
|
<%_ } else if (database !== 'None') { -%>
|
|
11
|
-
|
|
12
|
+
import sequelize from '<% if (architecture === "MVC") { %>../config/database.js<% } else { %>../../infrastructure/database/database.js<% } %>';
|
|
12
13
|
<%_ } -%>
|
|
13
14
|
|
|
15
|
+
const router = express.Router();
|
|
16
|
+
|
|
14
17
|
router.get('/', async (req, res) => {
|
|
15
18
|
const healthData = {
|
|
16
19
|
status: 'UP',
|
|
@@ -47,4 +50,4 @@ router.get('/', async (req, res) => {
|
|
|
47
50
|
res.status(HTTP_STATUS.OK).json(healthData);
|
|
48
51
|
});
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
export default router;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import request from 'supertest';
|
|
2
|
+
import express from 'express';
|
|
3
3
|
<% if (architecture === 'MVC') { -%>
|
|
4
|
-
|
|
4
|
+
import healthRoute from '@/routes/healthRoute.js';
|
|
5
5
|
<% } else { -%>
|
|
6
|
-
|
|
6
|
+
import healthRoute from '@/interfaces/routes/healthRoute.js';
|
|
7
7
|
<% } -%>
|
|
8
|
-
|
|
8
|
+
import HTTP_STATUS from '@/utils/httpCodes.js';
|
|
9
9
|
|
|
10
10
|
<%_ if (database === 'MongoDB') { -%>
|
|
11
|
+
import mongoose from 'mongoose';
|
|
11
12
|
jest.mock('mongoose', () => {
|
|
12
13
|
return {
|
|
13
14
|
connection: {
|
|
@@ -21,9 +22,11 @@ jest.mock('mongoose', () => {
|
|
|
21
22
|
};
|
|
22
23
|
});
|
|
23
24
|
<%_ } else if (database !== 'None') { -%>
|
|
24
|
-
|
|
25
|
+
import sequelize from '<% if (architecture === "MVC") { %>@/config/database.js<% } else { %>@/infrastructure/database/database.js<% } %>';
|
|
26
|
+
jest.mock('<% if (architecture === "MVC") { %>@/config/database.js<% } else { %>@/infrastructure/database/database.js<% } %>', () => {
|
|
25
27
|
return {
|
|
26
|
-
authenticate: jest.fn()
|
|
28
|
+
authenticate: jest.fn(),
|
|
29
|
+
sync: jest.fn()
|
|
27
30
|
};
|
|
28
31
|
});
|
|
29
32
|
<%_ } -%>
|
|
@@ -46,7 +49,6 @@ describe('Health Route', () => {
|
|
|
46
49
|
|
|
47
50
|
<%_ if (database === 'MongoDB') { -%>
|
|
48
51
|
it('should handle database ping failure and return 500', async () => {
|
|
49
|
-
const mongoose = require('mongoose');
|
|
50
52
|
mongoose.connection.db.admin.mockReturnValueOnce({
|
|
51
53
|
ping: jest.fn().mockRejectedValueOnce(new Error('DB Error'))
|
|
52
54
|
});
|
|
@@ -58,7 +60,6 @@ describe('Health Route', () => {
|
|
|
58
60
|
});
|
|
59
61
|
<%_ } else if (database !== 'None') { -%>
|
|
60
62
|
it('should handle database authentication failure and return 500', async () => {
|
|
61
|
-
const sequelize = require('<% if (architecture === "MVC") { %>@/config/database<% } else { %>@/infrastructure/database/database<% } %>');
|
|
62
63
|
sequelize.authenticate.mockRejectedValueOnce(new Error('DB Error'));
|
|
63
64
|
|
|
64
65
|
const res = await request(app).get('/health');
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import baseConfig from './jest.config.js';
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...baseConfig,
|
|
4
5
|
testMatch: ['<rootDir>/tests/e2e/**/*.test.ts', '<rootDir>/tests/e2e/**/*.test.js'],
|
|
5
6
|
testPathIgnorePatterns: ['/node_modules/'],
|
|
6
7
|
testTimeout: 30000,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { Kafka } from 'kafkajs';
|
|
2
|
+
import { env } from '../config/env.js';
|
|
3
3
|
|
|
4
4
|
const kafka = new Kafka({
|
|
5
5
|
clientId: 'nodejs-service',
|
|
6
6
|
brokers: [env.KAFKA_BROKER]
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
export { kafka };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { KAFKA_ACTIONS } from '<%- kafkaEventsPath %>.js';
|
|
3
3
|
|
|
4
4
|
const UserEventSchema = z.object({
|
|
5
5
|
action: z.enum(Object.values(KAFKA_ACTIONS)),
|
|
@@ -9,4 +9,4 @@ const UserEventSchema = z.object({
|
|
|
9
9
|
}),
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
export { UserEventSchema };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import BaseConsumer from '<%- baseConsumerPath %>.js';
|
|
2
|
+
import logger from '<%- loggerPath %>.js';
|
|
3
|
+
import { UserEventSchema } from '<%- userEventSchemaPath %>.js';
|
|
4
|
+
import ERROR_MESSAGES from '<%- errorMessagesPath %>.js';
|
|
5
|
+
import { KAFKA_ACTIONS } from '<%- kafkaEventsPath %>.js';
|
|
6
6
|
|
|
7
7
|
class WelcomeEmailConsumer extends BaseConsumer {
|
|
8
8
|
constructor() {
|
|
@@ -41,4 +41,4 @@ class WelcomeEmailConsumer extends BaseConsumer {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
|
|
44
|
+
export default WelcomeEmailConsumer;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { kafka } from '../config/kafka.js';
|
|
2
|
+
import logger from '<% if (architecture === "Clean Architecture") { %>../log/logger.js<% } else { %>../utils/logger.js<% } %>';
|
|
3
|
+
import WelcomeEmailConsumer from '<% if (architecture === "Clean Architecture") { %>../../interfaces/messaging/consumers/instances/welcomeEmailConsumer.js<% } else { %>../messaging/consumers/instances/welcomeEmailConsumer.js<% } %>';
|
|
3
4
|
|
|
4
5
|
let producer = null;
|
|
5
6
|
let consumer = null;
|
|
@@ -14,10 +15,7 @@ const connectKafka = async (retries = 10) => {
|
|
|
14
15
|
if (!consumer) consumer = kafka.consumer({ groupId: 'test-group' });
|
|
15
16
|
|
|
16
17
|
let attempt = 0;
|
|
17
|
-
|
|
18
|
-
// Note: Dynamic import used here for simplicity and to avoid startup crashes.
|
|
19
|
-
// In enterprise production, consider using Dependency Injection.
|
|
20
|
-
const WelcomeEmailConsumer = require('<% if (architecture === "Clean Architecture") { %>../../interfaces/messaging/consumers/instances/welcomeEmailConsumer<% } else { %>../messaging/consumers/instances/welcomeEmailConsumer<% } %>');
|
|
18
|
+
|
|
21
19
|
while (attempt < retries) {
|
|
22
20
|
try {
|
|
23
21
|
await producer.connect();
|
|
@@ -90,4 +88,4 @@ const disconnectKafka = async () => {
|
|
|
90
88
|
if (consumer) await consumer.disconnect();
|
|
91
89
|
};
|
|
92
90
|
|
|
93
|
-
|
|
91
|
+
export { connectKafka, sendMessage, disconnectKafka };
|
|
@@ -1,23 +1,21 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const existingAdmin = await db.collection('users').findOne({ email: adminEmail });
|
|
1
|
+
export const up = async (db, client) => {
|
|
2
|
+
const adminEmail = 'admin@example.com';
|
|
3
|
+
const existingAdmin = await db.collection('users').findOne({ email: adminEmail });
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
async down(db, client) {
|
|
20
|
-
// Optional: Undo the seed. Usually for seeds we might want to keep data, but strictly speaking 'down' should reverse 'up'.
|
|
21
|
-
// await db.collection('users').deleteOne({ email: 'admin@example.com' });
|
|
5
|
+
if (!existingAdmin) {
|
|
6
|
+
await db.collection('users').insertOne({
|
|
7
|
+
name: 'Admin User',
|
|
8
|
+
email: adminEmail,
|
|
9
|
+
createdAt: new Date(),
|
|
10
|
+
updatedAt: new Date()
|
|
11
|
+
});
|
|
12
|
+
console.log('Admin User seeded successfully');
|
|
13
|
+
} else {
|
|
14
|
+
console.log('Admin User already exists, skipping seed');
|
|
22
15
|
}
|
|
23
16
|
};
|
|
17
|
+
|
|
18
|
+
export const down = async (db, client) => {
|
|
19
|
+
// Optional: Undo the seed. Usually for seeds we might want to keep data, but strictly speaking 'down' should reverse 'up'.
|
|
20
|
+
// await db.collection('users').deleteOne({ email: 'admin@example.com' });
|
|
21
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { execSync } from 'child_process';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
4
7
|
|
|
5
8
|
// Set a specific port for E2E tests to avoid collisions with local development
|
|
6
9
|
process.env.PORT = '3001';
|
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
<%_
|
|
2
|
-
let loggerPath = './logger';
|
|
3
|
-
let dbPath = '../config/database';
|
|
4
|
-
let redisPath = '../config/redisClient';
|
|
5
|
-
let kafkaPath = '../services/kafkaService';
|
|
2
|
+
let loggerPath = './logger.js';
|
|
3
|
+
let dbPath = '../config/database.js';
|
|
4
|
+
let redisPath = '../config/redisClient.js';
|
|
5
|
+
let kafkaPath = '../services/kafkaService.js';
|
|
6
6
|
|
|
7
7
|
if (architecture === 'Clean Architecture') {
|
|
8
|
-
loggerPath = '../infrastructure/log/logger';
|
|
9
|
-
dbPath = '../infrastructure/database/database';
|
|
10
|
-
redisPath = '../infrastructure/caching/redisClient';
|
|
11
|
-
kafkaPath = '../infrastructure/messaging/kafkaClient';
|
|
8
|
+
loggerPath = '../infrastructure/log/logger.js';
|
|
9
|
+
dbPath = '../infrastructure/database/database.js';
|
|
10
|
+
redisPath = '../infrastructure/caching/redisClient.js';
|
|
11
|
+
kafkaPath = '../infrastructure/messaging/kafkaClient.js';
|
|
12
12
|
}
|
|
13
13
|
-%>
|
|
14
|
-
|
|
14
|
+
import logger from '<%- loggerPath %>';
|
|
15
|
+
<%_ if (database !== 'None') { -%>
|
|
16
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
17
|
+
import mongoose from 'mongoose';
|
|
18
|
+
<%_ } else { -%>
|
|
19
|
+
import sequelize from '<%- dbPath %>';
|
|
20
|
+
<%_ } -%>
|
|
21
|
+
<%_ if (caching === 'Redis') { -%>
|
|
22
|
+
import redisService from '<%- redisPath %>';
|
|
23
|
+
<%_ } -%>
|
|
24
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
25
|
+
import { disconnectKafka } from '<%- kafkaPath %>';
|
|
26
|
+
<%_ } -%>
|
|
27
|
+
<%_ } -%>
|
|
15
28
|
|
|
16
29
|
const setupGracefulShutdown = (server) => {
|
|
17
30
|
const gracefulShutdown = async (signal) => {
|
|
@@ -25,22 +38,18 @@ const setupGracefulShutdown = (server) => {
|
|
|
25
38
|
try {
|
|
26
39
|
<%_ if (database !== 'None') { -%>
|
|
27
40
|
<%_ if (database === 'MongoDB') { -%>
|
|
28
|
-
const mongoose = require('mongoose');
|
|
29
41
|
await mongoose.connection.close(false);
|
|
30
42
|
logger.info('MongoDB connection closed.');
|
|
31
43
|
<%_ } else { -%>
|
|
32
|
-
const sequelize = require('<%- dbPath %>');
|
|
33
44
|
await sequelize.close();
|
|
34
45
|
logger.info('Database connection closed.');
|
|
35
46
|
<%_ } -%>
|
|
36
47
|
<%_ } -%>
|
|
37
48
|
<%_ if (caching === 'Redis') { -%>
|
|
38
|
-
const redisService = require('<%- redisPath %>');
|
|
39
49
|
await redisService.quit();
|
|
40
50
|
logger.info('Redis connection closed.');
|
|
41
51
|
<%_ } -%>
|
|
42
52
|
<%_ if (communication === 'Kafka') { -%>
|
|
43
|
-
const { disconnectKafka } = require('<%- kafkaPath %>');
|
|
44
53
|
await disconnectKafka();
|
|
45
54
|
logger.info('Kafka connection closed.');
|
|
46
55
|
<%_ } -%>
|
|
@@ -62,4 +71,4 @@ const setupGracefulShutdown = (server) => {
|
|
|
62
71
|
process.on('SIGINT', () => gracefulShutdown('SIGINT'));
|
|
63
72
|
};
|
|
64
73
|
|
|
65
|
-
|
|
74
|
+
export default setupGracefulShutdown;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { betterAuth } from "better-auth";
|
|
2
2
|
<% if (database === 'MongoDB') { %>import { mongodbAdapter } from "better-auth/adapters/mongodb";
|
|
3
3
|
import mongoose from "mongoose";<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>import { sequelizeAdapter } from "better-auth/adapters/sequelize";
|
|
4
|
-
import sequelize from "./database";<% } %>
|
|
4
|
+
import sequelize from "./database<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>";<% } %>
|
|
5
5
|
|
|
6
6
|
export const auth = betterAuth({
|
|
7
7
|
database: <% if (database === 'MongoDB') { %>mongodbAdapter(mongoose.connection.db)<% } else if (database === 'MySQL' || database === 'PostgreSQL') { %>sequelizeAdapter(sequelize)<% } else { %>null // Better-Auth requires a database adapter<% } %>,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<% if (auth === 'Better-Auth') { %>
|
|
2
|
-
import { auth } from '../config/auth<% if (language === 'TypeScript') { %>.ts<% } %>';
|
|
2
|
+
import { auth } from '../config/auth<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>';
|
|
3
3
|
|
|
4
4
|
export const register = async (req, res, next) => {
|
|
5
5
|
try {
|
|
@@ -34,7 +34,7 @@ export const login = async (req, res, next) => {
|
|
|
34
34
|
<% } else if (auth === 'JWT') { %>
|
|
35
35
|
import jwt from 'jsonwebtoken';
|
|
36
36
|
import bcrypt from 'bcryptjs';
|
|
37
|
-
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
|
|
37
|
+
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>';
|
|
38
38
|
|
|
39
39
|
// Mock User database (In production, use your database models)
|
|
40
40
|
const users = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import jwt from 'jsonwebtoken';
|
|
2
|
-
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
|
|
2
|
+
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>';
|
|
3
3
|
|
|
4
4
|
export const authMiddleware = (req, res, next) => {
|
|
5
5
|
const authHeader = req.headers.authorization;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import multer from 'multer';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } %>';
|
|
3
|
+
import { ApiError } from '../utils/errorMiddleware<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>';
|
|
4
4
|
|
|
5
5
|
// Storage configuration
|
|
6
6
|
const storage = multer.diskStorage({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import express from 'express';
|
|
2
2
|
<% if (auth === 'OAuth' || googleLogin === 'Google Login') { %>import passport from 'passport';<% } %>
|
|
3
|
-
import * as authController from '../controllers/authController<% if (language === 'TypeScript') { %>.ts<% } %>';
|
|
3
|
+
import * as authController from '../controllers/authController<% if (language === 'TypeScript') { %>.ts<% } else { %>.js<% } %>';
|
|
4
4
|
|
|
5
5
|
const router = express.Router();
|
|
6
6
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
import { errorMiddleware } from '<% if (architecture === "MVC") { %>@/utils/errorMiddleware.js<% } else { %>@/infrastructure/webserver/middleware/errorMiddleware.js<% } %>';
|
|
2
|
+
import { ApiError } from '@/errors/ApiError.js';
|
|
3
|
+
import HTTP_STATUS from '@/utils/httpCodes.js';
|
|
4
|
+
import logger from '<% if (architecture === "MVC") { %>@/utils/logger.js<% } else { %>@/infrastructure/log/logger.js<% } %>';
|
|
5
5
|
|
|
6
|
-
jest.mock('<% if (architecture === "MVC") { %>@/utils/logger<% } else { %>@/infrastructure/log/logger<% } %>');
|
|
6
|
+
jest.mock('<% if (architecture === "MVC") { %>@/utils/logger.js<% } else { %>@/infrastructure/log/logger.js<% } %>');
|
|
7
7
|
|
|
8
8
|
describe('Error Middleware', () => {
|
|
9
9
|
let mockRequest;
|
|
@@ -68,7 +68,6 @@ describe('Error Middleware', () => {
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
it('should handle error without stack trace', () => {
|
|
71
|
-
const { ApiError } = require('@/errors/ApiError');
|
|
72
71
|
const customError = new ApiError(500, 'No Stack', false);
|
|
73
72
|
delete customError.stack;
|
|
74
73
|
errorMiddleware(customError, mockRequest, mockResponse, nextFunction);
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import logger from '../utils/logger.js';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
3
4
|
|
|
4
5
|
if (process.env.NODE_ENV !== 'production') {
|
|
5
|
-
|
|
6
|
+
dotenv.config();
|
|
6
7
|
}
|
|
7
8
|
const envSchema = z.object({
|
|
8
9
|
NODE_ENV: z.enum(['development', 'production', 'test']).default('development'),
|
|
@@ -43,4 +44,4 @@ if (!_env.success) {
|
|
|
43
44
|
|
|
44
45
|
const env = _env.data;
|
|
45
46
|
|
|
46
|
-
|
|
47
|
+
export { env };
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import YAML from 'yamljs';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
3
7
|
|
|
4
8
|
const swaggerDocument = YAML.load(path.join(__dirname, 'swagger.yml'));
|
|
5
9
|
|
|
6
|
-
|
|
10
|
+
export default swaggerDocument;
|