nodejs-quickstart-structure 1.9.4 → 1.10.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.
- package/CHANGELOG.md +9 -0
- package/README.md +7 -7
- package/bin/index.js +2 -2
- package/docs/generateCase.md +160 -164
- package/lib/modules/app-setup.js +65 -1
- package/lib/prompts.js +1 -1
- package/package.json +4 -2
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +25 -11
- package/templates/clean-architecture/js/src/interfaces/controllers/{userController.js → userController.js.ejs} +23 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +27 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -0
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +17 -0
- package/templates/clean-architecture/ts/src/index.ts.ejs +51 -20
- package/templates/clean-architecture/ts/src/interfaces/controllers/{userController.ts → userController.ts.ejs} +28 -1
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -0
- package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -0
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -0
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +27 -0
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -0
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +15 -0
- package/templates/common/README.md.ejs +27 -0
- package/templates/common/database/js/mongoose.js.ejs +0 -1
- package/templates/common/database/ts/mongoose.ts.ejs +0 -1
- package/templates/common/package.json.ejs +4 -1
- package/templates/mvc/js/src/controllers/userController.js.ejs +55 -0
- package/templates/mvc/js/src/graphql/context.js.ejs +7 -0
- package/templates/mvc/js/src/graphql/index.js.ejs +5 -0
- package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -0
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +25 -0
- package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -0
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +17 -0
- package/templates/mvc/js/src/index.js.ejs +38 -26
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +56 -1
- package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -0
- package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -0
- package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -0
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +27 -0
- package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -0
- package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +15 -0
- package/templates/mvc/ts/src/index.ts.ejs +54 -26
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const cors = require('cors');
|
|
3
3
|
require('dotenv').config();
|
|
4
|
-
<% if (communication === 'REST APIs'
|
|
5
|
-
<% if (communication === 'Kafka') {
|
|
6
|
-
<% if (communication === '
|
|
4
|
+
<%_ if (communication === 'REST APIs') { -%>const apiRoutes = require('./routes/api');<%_ } -%>
|
|
5
|
+
<%_ if (communication === 'Kafka') { -%>const { connectKafka, sendMessage } = require('./services/kafkaService');<%_ } -%>
|
|
6
|
+
<%_ if (communication === 'GraphQL') { -%>
|
|
7
|
+
const { ApolloServer } = require('@apollo/server');
|
|
8
|
+
const { expressMiddleware } = require('@apollo/server/express4');
|
|
9
|
+
const { ApolloServerPluginLandingPageLocalDefault } = require('@apollo/server/plugin/landingPage/default');
|
|
10
|
+
const { typeDefs, resolvers } = require('./graphql');
|
|
11
|
+
const { gqlContext } = require('./graphql/context');
|
|
12
|
+
<% } -%>
|
|
13
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
7
14
|
const swaggerUi = require('swagger-ui-express');
|
|
8
15
|
const swaggerSpecs = require('./config/swagger');
|
|
9
|
-
<% } -%>
|
|
16
|
+
<%_ } -%>
|
|
10
17
|
|
|
11
18
|
const app = express();
|
|
12
19
|
const PORT = process.env.PORT || 3000;
|
|
@@ -17,22 +24,18 @@ app.use(cors());
|
|
|
17
24
|
app.use(express.json());
|
|
18
25
|
app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));
|
|
19
26
|
|
|
20
|
-
<% if (communication === 'REST APIs') { -%>
|
|
27
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
21
28
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
|
|
22
|
-
<% } -%>
|
|
23
|
-
|
|
24
|
-
<% if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
|
|
29
|
+
<%_ } -%>
|
|
30
|
+
<%_ if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
|
|
25
31
|
// View Engine Setup
|
|
26
32
|
const path = require('path');
|
|
27
33
|
app.set('views', path.join(__dirname, 'views'));
|
|
28
34
|
app.set('view engine', '<%= viewEngine.toLowerCase() %>');
|
|
29
|
-
app.use(express.static(path.join(__dirname, '../public')));<% }
|
|
30
|
-
|
|
31
|
-
// Routes
|
|
32
|
-
<% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { -%>
|
|
35
|
+
app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
|
|
36
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
33
37
|
app.use('/api', apiRoutes);
|
|
34
|
-
<% } -%>
|
|
35
|
-
<% if (viewEngine && viewEngine !== 'None') { -%>
|
|
38
|
+
<%_ } -%><% if (viewEngine && viewEngine !== 'None') { -%>
|
|
36
39
|
app.get('/', (req, res) => {
|
|
37
40
|
res.render('index', {
|
|
38
41
|
projectName: 'NodeJS Service',
|
|
@@ -42,24 +45,33 @@ app.get('/', (req, res) => {
|
|
|
42
45
|
});
|
|
43
46
|
});
|
|
44
47
|
<% } -%>
|
|
45
|
-
|
|
46
48
|
app.get('/health', (req, res) => {
|
|
47
49
|
res.json({ status: 'UP' });
|
|
48
50
|
});
|
|
49
51
|
|
|
50
52
|
// Start Server Logic
|
|
51
53
|
const startServer = async () => {
|
|
52
|
-
|
|
54
|
+
<%_ if (communication === 'GraphQL') { -%>
|
|
55
|
+
// GraphQL Setup
|
|
56
|
+
const server = new ApolloServer({
|
|
57
|
+
typeDefs,
|
|
58
|
+
resolvers,
|
|
59
|
+
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
|
|
60
|
+
});
|
|
61
|
+
await server.start();
|
|
62
|
+
app.use('/graphql', expressMiddleware(server, { context: gqlContext }));
|
|
63
|
+
<%_ } -%>
|
|
64
|
+
app.listen(PORT, () => {
|
|
65
|
+
logger.info(`Server running on port ${PORT}`);
|
|
53
66
|
<%_ if (communication === 'Kafka') { -%>
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
logger.error('Failed to connect to Kafka:', err);
|
|
61
|
-
}
|
|
67
|
+
connectKafka().then(() => {
|
|
68
|
+
logger.info('Kafka connected');
|
|
69
|
+
sendMessage('test-topic', 'Hello Kafka from MVC JS!');
|
|
70
|
+
}).catch(err => {
|
|
71
|
+
logger.error('Failed to connect to Kafka:', err);
|
|
72
|
+
});
|
|
62
73
|
<%_ } -%>
|
|
74
|
+
});
|
|
63
75
|
};
|
|
64
76
|
|
|
65
77
|
<%_ if (database !== 'None') { -%>
|
|
@@ -78,7 +90,7 @@ const syncDatabase = async () => {
|
|
|
78
90
|
logger.info('Database synced');
|
|
79
91
|
|
|
80
92
|
// Start Server after DB is ready
|
|
81
|
-
|
|
93
|
+
await startServer();
|
|
82
94
|
break;
|
|
83
95
|
} catch (err) {
|
|
84
96
|
logger.error('Database sync failed:', err);
|
|
@@ -91,5 +103,5 @@ const syncDatabase = async () => {
|
|
|
91
103
|
|
|
92
104
|
syncDatabase();
|
|
93
105
|
<%_ } else { -%>
|
|
94
|
-
|
|
106
|
+
startServer();
|
|
95
107
|
<%_ } -%>
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
<% if (communication !== 'GraphQL') { -%>
|
|
1
2
|
import { Request, Response } from 'express';
|
|
2
|
-
import User from '@/models/User';
|
|
3
3
|
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
4
|
+
<% } -%>
|
|
5
|
+
import User from '@/models/User';
|
|
4
6
|
import logger from '@/utils/logger';
|
|
5
7
|
<%_ if (caching === 'Redis') { -%>
|
|
6
8
|
import cacheService from '@/config/redisClient';
|
|
@@ -9,6 +11,58 @@ import cacheService from '@/config/memoryCache';
|
|
|
9
11
|
<%_ } -%>
|
|
10
12
|
|
|
11
13
|
export class UserController {
|
|
14
|
+
<% if (communication === 'GraphQL') { -%>
|
|
15
|
+
async getUsers() {
|
|
16
|
+
try {
|
|
17
|
+
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
18
|
+
const users = await cacheService.getOrSet('users:all', async () => {
|
|
19
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
20
|
+
return await User.find();
|
|
21
|
+
<%_ } else if (database === 'None') { -%>
|
|
22
|
+
return User.mockData;
|
|
23
|
+
<%_ } else { -%>
|
|
24
|
+
return await User.findAll();
|
|
25
|
+
<%_ } -%>
|
|
26
|
+
}, 60);
|
|
27
|
+
<%_ } else { -%>
|
|
28
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
29
|
+
const users = await User.find();
|
|
30
|
+
<%_ } else if (database === 'None') { -%>
|
|
31
|
+
const users = User.mockData;
|
|
32
|
+
<%_ } else { -%>
|
|
33
|
+
const users = await User.findAll();
|
|
34
|
+
<%_ } -%>
|
|
35
|
+
<%_ } -%>
|
|
36
|
+
return users;
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error('Error fetching users:', error);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async createUser(data: { name: string, email: string }) {
|
|
44
|
+
try {
|
|
45
|
+
const { name, email } = data;
|
|
46
|
+
<%_ if (database === 'None') { -%>
|
|
47
|
+
const newUser = { id: String(User.mockData.length + 1), name, email };
|
|
48
|
+
User.mockData.push(newUser);
|
|
49
|
+
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
50
|
+
await cacheService.del('users:all');
|
|
51
|
+
<%_ } -%>
|
|
52
|
+
return newUser;
|
|
53
|
+
<%_ } else { -%>
|
|
54
|
+
const user = await User.create({ name, email });
|
|
55
|
+
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
56
|
+
await cacheService.del('users:all');
|
|
57
|
+
<%_ } -%>
|
|
58
|
+
return user;
|
|
59
|
+
<%_ } -%>
|
|
60
|
+
} catch (error) {
|
|
61
|
+
logger.error('Error creating user:', error);
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
<% } else { -%>
|
|
12
66
|
async getUsers(req: Request, res: Response) {
|
|
13
67
|
try {
|
|
14
68
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
@@ -67,5 +121,6 @@ export class UserController {
|
|
|
67
121
|
}
|
|
68
122
|
}
|
|
69
123
|
}
|
|
124
|
+
<% } -%>
|
|
70
125
|
}
|
|
71
126
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Request } from 'express';
|
|
2
|
+
|
|
3
|
+
export interface MyContext {
|
|
4
|
+
token?: string;
|
|
5
|
+
// user?: User;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
|
|
9
|
+
// Setup authorization or context here
|
|
10
|
+
const token = req.headers.authorization || '';
|
|
11
|
+
return { token };
|
|
12
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { GraphQLError } from 'graphql';
|
|
2
|
+
import { UserController } from '@/controllers/userController';
|
|
3
|
+
|
|
4
|
+
const userController = new UserController();
|
|
5
|
+
|
|
6
|
+
export const userResolvers = {
|
|
7
|
+
Query: {
|
|
8
|
+
getAllUsers: async () => {
|
|
9
|
+
try {
|
|
10
|
+
return await userController.getUsers();
|
|
11
|
+
} catch (error: unknown) {
|
|
12
|
+
const message = error instanceof Error ? error.message : 'Internal server error';
|
|
13
|
+
throw new GraphQLError(message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
Mutation: {
|
|
18
|
+
createUser: async (_: unknown, { name, email }: { name: string, email: string }) => {
|
|
19
|
+
try {
|
|
20
|
+
return await userController.createUser({ name, email });
|
|
21
|
+
} catch (error: unknown) {
|
|
22
|
+
const message = error instanceof Error ? error.message : 'Internal server error';
|
|
23
|
+
throw new GraphQLError(message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
};
|
|
@@ -6,11 +6,19 @@ import rateLimit from 'express-rate-limit';
|
|
|
6
6
|
import dotenv from 'dotenv';
|
|
7
7
|
import logger from '@/utils/logger';
|
|
8
8
|
import morgan from 'morgan';
|
|
9
|
-
<% if (communication === 'REST APIs'
|
|
9
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
10
|
+
import apiRoutes from '@/routes/api';<%_ } -%>
|
|
10
11
|
<% if (communication === 'REST APIs') { %>
|
|
11
12
|
import swaggerUi from 'swagger-ui-express';
|
|
12
13
|
import swaggerSpecs from '@/config/swagger';<% } -%>
|
|
13
|
-
<% if (communication === 'Kafka') {
|
|
14
|
+
<%_ if (communication === 'Kafka') { -%>import { KafkaService } from '@/services/kafkaService';<%_ } -%>
|
|
15
|
+
<%_ if (communication === 'GraphQL') { -%>
|
|
16
|
+
import { ApolloServer } from '@apollo/server';
|
|
17
|
+
import { expressMiddleware } from '@apollo/server/express4';
|
|
18
|
+
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
|
|
19
|
+
import { typeDefs, resolvers } from '@/graphql';
|
|
20
|
+
import { gqlContext, MyContext } from '@/graphql/context';
|
|
21
|
+
<% } -%>
|
|
14
22
|
|
|
15
23
|
dotenv.config();
|
|
16
24
|
|
|
@@ -18,7 +26,21 @@ const app = express();
|
|
|
18
26
|
const port = process.env.PORT || 3000;
|
|
19
27
|
|
|
20
28
|
// Security Middleware
|
|
29
|
+
<%_ if (communication === 'GraphQL') { -%>
|
|
30
|
+
app.use(helmet({
|
|
31
|
+
crossOriginEmbedderPolicy: false,
|
|
32
|
+
contentSecurityPolicy: {
|
|
33
|
+
directives: {
|
|
34
|
+
imgSrc: [`'self'`, 'data:', 'apollo-server-landing-page.cdn.apollographql.com'],
|
|
35
|
+
scriptSrc: [`'self'`, `https: 'unsafe-inline'`],
|
|
36
|
+
manifestSrc: [`'self'`, 'apollo-server-landing-page.cdn.apollographql.com'],
|
|
37
|
+
frameSrc: [`'self'`, 'sandbox.embed.apollographql.com'],
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
}));
|
|
41
|
+
<%_ } else { -%>
|
|
21
42
|
app.use(helmet());
|
|
43
|
+
<%_ } -%>
|
|
22
44
|
app.use(hpp());
|
|
23
45
|
app.use(cors({ origin: '*', methods: ['GET', 'POST', 'PUT', 'DELETE'] }));
|
|
24
46
|
const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 100 });
|
|
@@ -26,23 +48,18 @@ app.use(limiter);
|
|
|
26
48
|
|
|
27
49
|
app.use(express.json());
|
|
28
50
|
app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
|
|
29
|
-
|
|
30
|
-
<% if (communication === 'REST APIs') { -%>
|
|
51
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
31
52
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
|
|
32
|
-
<% } -%>
|
|
33
|
-
|
|
34
|
-
<% if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
|
|
53
|
+
<%_ } -%>
|
|
54
|
+
<%_ if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
|
|
35
55
|
// View Engine Setup
|
|
36
56
|
import path from 'path';
|
|
37
57
|
app.set('views', path.join(__dirname, 'views'));
|
|
38
58
|
app.set('view engine', '<%= viewEngine.toLowerCase() %>');
|
|
39
|
-
app.use(express.static(path.join(__dirname, '../public')));<% }
|
|
40
|
-
|
|
41
|
-
// Routes
|
|
42
|
-
<% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { -%>
|
|
59
|
+
app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
|
|
60
|
+
<%_ if (communication === 'REST APIs') { -%>
|
|
43
61
|
app.use('/api', apiRoutes);
|
|
44
|
-
<% } -%>
|
|
45
|
-
<% if (viewEngine && viewEngine !== 'None') { -%>
|
|
62
|
+
<%_ } -%><% if (viewEngine && viewEngine !== 'None') { -%>
|
|
46
63
|
app.get('/', (req: Request, res: Response) => {
|
|
47
64
|
res.render('index', {
|
|
48
65
|
projectName: 'NodeJS Service',
|
|
@@ -52,25 +69,36 @@ app.get('/', (req: Request, res: Response) => {
|
|
|
52
69
|
});
|
|
53
70
|
});
|
|
54
71
|
<% } -%>
|
|
55
|
-
|
|
56
72
|
app.get('/health', (req: Request, res: Response) => {
|
|
57
73
|
res.json({ status: 'UP' });
|
|
58
74
|
});
|
|
59
75
|
|
|
60
76
|
// Start Server Logic
|
|
61
77
|
const startServer = async () => {
|
|
62
|
-
|
|
78
|
+
<%_ if (communication === 'GraphQL') { -%>
|
|
79
|
+
// GraphQL Setup
|
|
80
|
+
const server = new ApolloServer<MyContext>({
|
|
81
|
+
typeDefs,
|
|
82
|
+
resolvers,
|
|
83
|
+
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
|
|
84
|
+
});
|
|
85
|
+
await server.start();
|
|
86
|
+
app.use('/graphql', expressMiddleware(server, { context: gqlContext }));
|
|
87
|
+
<%_ } -%>
|
|
88
|
+
app.listen(port, () => {
|
|
89
|
+
logger.info(`Server running on port ${port}`);
|
|
63
90
|
<%_ if (communication === 'Kafka') { -%>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
91
|
+
try {
|
|
92
|
+
const kafkaService = new KafkaService();
|
|
93
|
+
kafkaService.connect().then(() => {
|
|
94
|
+
logger.info('Kafka connected');
|
|
95
|
+
kafkaService.sendMessage('test-topic', 'Hello Kafka from MVC TS!');
|
|
96
|
+
});
|
|
97
|
+
} catch (err) {
|
|
98
|
+
logger.error('Failed to connect to Kafka:', err);
|
|
99
|
+
}
|
|
73
100
|
<%_ } -%>
|
|
101
|
+
});
|
|
74
102
|
};
|
|
75
103
|
|
|
76
104
|
<%_ if (database !== 'None') { -%>
|
|
@@ -88,7 +116,7 @@ const syncDatabase = async () => {
|
|
|
88
116
|
<%_ } -%>
|
|
89
117
|
logger.info('Database synced');
|
|
90
118
|
// Start Server after DB is ready
|
|
91
|
-
|
|
119
|
+
await startServer();
|
|
92
120
|
break;
|
|
93
121
|
} catch (error) {
|
|
94
122
|
logger.error('Error syncing database:', error);
|
|
@@ -101,5 +129,5 @@ const syncDatabase = async () => {
|
|
|
101
129
|
|
|
102
130
|
syncDatabase();
|
|
103
131
|
<%_ } else { -%>
|
|
104
|
-
|
|
132
|
+
startServer();
|
|
105
133
|
<%_ } -%>
|