nodejs-quickstart-structure 2.0.1 → 2.1.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.
- package/CHANGELOG.md +25 -0
- package/README.md +64 -66
- package/bin/index.js +5 -2
- package/lib/generator.js +10 -4
- package/lib/modules/app-setup.js +76 -6
- package/lib/modules/auth-setup.js +143 -0
- package/lib/modules/caching-setup.js +8 -1
- package/lib/modules/config-files.js +6 -0
- package/lib/modules/database-setup.js +2 -1
- package/lib/modules/project-setup.js +1 -0
- package/lib/prompts.js +39 -0
- package/package.json +5 -4
- package/templates/clean-architecture/js/src/domain/models/User.js +3 -1
- package/templates/clean-architecture/js/src/index.js.ejs +2 -0
- package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +12 -3
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +25 -2
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.spec.js.ejs +38 -1
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +3 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.spec.js.ejs +51 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.spec.js.ejs +14 -0
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +41 -4
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.spec.js.ejs +70 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -6
- package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +55 -22
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +10 -5
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
- package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/user.types.js.ejs +1 -1
- package/templates/clean-architecture/js/src/interfaces/routes/api.js.ejs +15 -0
- package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +4 -0
- package/templates/clean-architecture/js/src/usecases/CreateUser.js.ejs +34 -0
- package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +12 -3
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js.ejs +27 -0
- package/templates/clean-architecture/js/src/usecases/DeleteUser.spec.js.ejs +9 -1
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js.ejs +36 -0
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +23 -1
- package/templates/clean-architecture/js/src/usecases/GetUserById.js.ejs +36 -0
- package/templates/clean-architecture/js/src/usecases/GetUserById.spec.js.ejs +48 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js.ejs +28 -0
- package/templates/clean-architecture/js/src/usecases/UpdateUser.spec.js.ejs +9 -1
- package/templates/clean-architecture/js/src/utils/errorMessages.js +1 -0
- package/templates/clean-architecture/js/src/utils/httpCodes.js +2 -0
- package/templates/clean-architecture/ts/src/config/env.ts.ejs +12 -3
- package/templates/clean-architecture/ts/src/domain/user.ts +3 -1
- package/templates/clean-architecture/ts/src/index.ts.ejs +4 -0
- package/templates/clean-architecture/ts/src/infrastructure/repositories/UserRepository.spec.ts.ejs +71 -10
- package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +32 -3
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.spec.ts.ejs +43 -9
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +57 -15
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +57 -24
- package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +14 -8
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.spec.ts.ejs +33 -10
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +15 -5
- package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/user.types.ts.ejs +1 -1
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +9 -1
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts.ejs +16 -0
- package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +12 -3
- package/templates/clean-architecture/ts/src/usecases/createUser.ts.ejs +35 -0
- package/templates/clean-architecture/ts/src/usecases/deleteUser.spec.ts.ejs +10 -1
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts.ejs +24 -0
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +9 -1
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts.ejs +21 -0
- package/templates/clean-architecture/ts/src/usecases/getUserById.spec.ts.ejs +55 -0
- package/templates/clean-architecture/ts/src/usecases/getUserById.ts.ejs +23 -0
- package/templates/clean-architecture/ts/src/usecases/updateUser.spec.ts.ejs +10 -1
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts.ejs +25 -0
- package/templates/clean-architecture/ts/src/utils/errorMessages.ts +1 -0
- package/templates/clean-architecture/ts/src/utils/httpCodes.ts +1 -0
- package/templates/common/.cursorrules.ejs +9 -0
- package/templates/common/.env.example.ejs +17 -10
- package/templates/common/README.md.ejs +63 -18
- package/templates/common/auth/js/controllers/authController.js.ejs +170 -0
- package/templates/common/auth/js/controllers/authController.spec.js.ejs +148 -0
- package/templates/common/auth/js/middleware/authMiddleware.js.ejs +58 -0
- package/templates/common/auth/js/middleware/authMiddleware.spec.js.ejs +108 -0
- package/templates/common/auth/js/routes/authRoutes.js.ejs +16 -0
- package/templates/common/auth/js/services/jwtService.js.ejs +54 -0
- package/templates/common/auth/js/services/jwtService.spec.js.ejs +84 -0
- package/templates/common/auth/ts/controllers/authController.spec.ts.ejs +161 -0
- package/templates/common/auth/ts/controllers/authController.ts.ejs +167 -0
- package/templates/common/auth/ts/middleware/authMiddleware.spec.ts.ejs +128 -0
- package/templates/common/auth/ts/middleware/authMiddleware.ts.ejs +59 -0
- package/templates/common/auth/ts/routes/authRoutes.ts.ejs +20 -0
- package/templates/common/auth/ts/services/jwtService.spec.ts.ejs +89 -0
- package/templates/common/auth/ts/services/jwtService.ts.ejs +60 -0
- package/templates/common/babel.config.js.ejs +5 -0
- package/templates/common/caching/clean/js/CreateUser.js.ejs +14 -5
- package/templates/common/caching/clean/js/DeleteUser.js.ejs +2 -1
- package/templates/common/caching/clean/js/GetUserById.js.ejs +39 -0
- package/templates/common/caching/clean/js/UpdateUser.js.ejs +2 -1
- package/templates/common/caching/clean/ts/createUser.ts.ejs +14 -6
- package/templates/common/caching/clean/ts/deleteUser.ts.ejs +2 -1
- package/templates/common/caching/clean/ts/getUserById.ts.ejs +32 -0
- package/templates/common/caching/clean/ts/updateUser.ts.ejs +2 -1
- package/templates/common/caching/js/memoryCache.spec.js.ejs +2 -0
- package/templates/common/caching/js/redisClient.spec.js.ejs +2 -0
- package/templates/common/caching/ts/memoryCache.spec.ts.ejs +2 -0
- package/templates/common/caching/ts/redisClient.spec.ts.ejs +2 -0
- package/templates/common/database/js/models/User.js.ejs +14 -1
- package/templates/common/database/js/models/User.js.mongoose.ejs +7 -0
- package/templates/common/database/js/models/User.spec.js.ejs +12 -0
- package/templates/common/database/js/mongoose.spec.js.ejs +2 -0
- package/templates/common/database/ts/models/User.spec.ts.ejs +10 -0
- package/templates/common/database/ts/models/User.ts.ejs +17 -0
- package/templates/common/database/ts/models/User.ts.mongoose.ejs +8 -0
- package/templates/common/database/ts/mongoose.spec.ts.ejs +2 -0
- package/templates/common/docker-compose.yml.ejs +12 -0
- package/templates/common/ecosystem.config.js.ejs +9 -3
- package/templates/common/eslint.config.mjs.ejs +3 -0
- package/templates/common/jest.config.js.ejs +13 -9
- package/templates/common/kafka/js/messaging/baseConsumer.js.ejs +1 -1
- package/templates/common/kafka/js/services/kafkaService.js.ejs +1 -1
- package/templates/common/migrations/init.js.ejs +5 -4
- package/templates/common/package.json.ejs +11 -2
- package/templates/common/prompts/project-context.md.ejs +8 -1
- package/templates/common/src/tests/e2e/e2e.users.test.js.ejs +149 -107
- package/templates/common/src/tests/e2e/e2e.users.test.ts.ejs +88 -47
- package/templates/common/swagger.yml.ejs +148 -0
- package/templates/common/tsconfig.eslint.json +15 -0
- package/templates/common/tsconfig.json +3 -1
- package/templates/common/views/ejs/index.ejs +264 -30
- package/templates/common/views/ejs/login.ejs.ejs +244 -0
- package/templates/common/views/ejs/signup.ejs.ejs +282 -0
- package/templates/common/views/pug/index.pug +269 -38
- package/templates/common/views/pug/login.pug.ejs +195 -0
- package/templates/common/views/pug/signup.pug.ejs +241 -0
- package/templates/db/mysql/V1__Initial_Setup.sql.ejs +6 -0
- package/templates/db/postgres/V1__Initial_Setup.sql.ejs +6 -0
- package/templates/mvc/js/src/config/env.js.ejs +12 -3
- package/templates/mvc/js/src/controllers/userController.js.ejs +29 -5
- package/templates/mvc/js/src/controllers/userController.spec.js.ejs +27 -12
- package/templates/mvc/js/src/graphql/context.js.ejs +14 -3
- package/templates/mvc/js/src/graphql/context.spec.js.ejs +36 -21
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +10 -5
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.spec.js.ejs +32 -10
- package/templates/mvc/js/src/graphql/typeDefs/user.types.js.ejs +1 -1
- package/templates/mvc/js/src/index.js.ejs +16 -3
- package/templates/mvc/js/src/routes/api.js.ejs +14 -0
- package/templates/mvc/js/src/routes/api.spec.js.ejs +3 -0
- package/templates/mvc/js/src/utils/errorMessages.js +1 -0
- package/templates/mvc/js/src/utils/httpCodes.js +1 -0
- package/templates/mvc/ts/src/config/env.ts.ejs +12 -3
- package/templates/mvc/ts/src/controllers/userController.spec.ts.ejs +95 -7
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +68 -11
- package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +36 -23
- package/templates/mvc/ts/src/graphql/context.ts.ejs +15 -6
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.spec.ts.ejs +32 -10
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +15 -5
- package/templates/mvc/ts/src/graphql/typeDefs/user.types.ts.ejs +1 -1
- package/templates/mvc/ts/src/index.ts.ejs +15 -3
- package/templates/mvc/ts/src/routes/api.spec.ts.ejs +6 -0
- package/templates/mvc/ts/src/routes/api.ts.ejs +15 -0
- package/templates/mvc/ts/src/utils/errorMessages.ts +1 -0
- package/templates/mvc/ts/src/utils/httpCodes.ts +1 -0
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +0 -12
- package/templates/clean-architecture/js/src/usecases/CreateUser.js +0 -14
- package/templates/clean-architecture/js/src/usecases/DeleteUser.js +0 -11
- package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +0 -12
- package/templates/clean-architecture/js/src/usecases/UpdateUser.js +0 -11
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +0 -13
- package/templates/clean-architecture/ts/src/usecases/createUser.ts +0 -13
- package/templates/clean-architecture/ts/src/usecases/deleteUser.ts +0 -9
- package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +0 -10
- package/templates/clean-architecture/ts/src/usecases/updateUser.ts +0 -9
- package/templates/mvc/js/src/routes/api.js +0 -10
- package/templates/mvc/ts/src/routes/api.ts +0 -12
|
@@ -4,6 +4,8 @@ const cors = require('cors');
|
|
|
4
4
|
<%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>const apiRoutes = require('./routes/api');<%_ } %>
|
|
5
5
|
const healthRoutes = require('./routes/healthRoute');
|
|
6
6
|
<%_ if (communication === 'Kafka') { -%>const { connectKafka, sendMessage } = require('./services/kafkaService');<%_ } -%>
|
|
7
|
+
<%_ if (auth.includes('JWT')) { -%>const authRoutes = require('./routes/authRoutes');<%_ } -%>
|
|
8
|
+
|
|
7
9
|
<%_ if (communication === 'GraphQL') { -%>
|
|
8
10
|
const { ApolloServer } = require('@apollo/server');
|
|
9
11
|
const { expressMiddleware } = require('@as-integrations/express4');
|
|
@@ -27,6 +29,7 @@ const { errorMiddleware } = require('./utils/errorMiddleware');
|
|
|
27
29
|
|
|
28
30
|
app.use(cors());
|
|
29
31
|
app.use(express.json());
|
|
32
|
+
app.use(express.urlencoded({ extended: true }));
|
|
30
33
|
app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));
|
|
31
34
|
|
|
32
35
|
<%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
|
|
@@ -40,15 +43,25 @@ app.set('view engine', '<%= viewEngine.toLowerCase() %>');
|
|
|
40
43
|
app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
|
|
41
44
|
<%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
|
|
42
45
|
app.use('/api', apiRoutes);
|
|
43
|
-
<%_ } -%><% if (
|
|
46
|
+
<%_ } -%><%_ if (auth.includes('JWT')) { -%>
|
|
47
|
+
app.use('/api/auth', authRoutes);
|
|
48
|
+
<%_ } -%>
|
|
49
|
+
|
|
50
|
+
<% if (viewEngine && viewEngine !== 'None') { -%>
|
|
44
51
|
app.get('/', (req, res) => {
|
|
45
52
|
res.render('index', {
|
|
46
|
-
projectName: '
|
|
53
|
+
projectName: '<%= projectName %>',
|
|
47
54
|
architecture: 'MVC',
|
|
48
55
|
database: '<%= database %>',
|
|
49
|
-
communication: '<%= communication %>'
|
|
56
|
+
communication: '<%= communication %>',
|
|
57
|
+
auth: <%- JSON.stringify(auth) %>
|
|
50
58
|
});
|
|
51
59
|
});
|
|
60
|
+
|
|
61
|
+
<% if (auth.includes('JWT')) { %>
|
|
62
|
+
app.get('/login', (req, res) => res.render('login', { projectName: '<%= projectName %>' }));
|
|
63
|
+
app.get('/signup', (req, res) => res.render('signup', { projectName: '<%= projectName %>' }));
|
|
64
|
+
<% } %>
|
|
52
65
|
<% } -%>
|
|
53
66
|
app.use('/health', healthRoutes);
|
|
54
67
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const { Router } = require('express');
|
|
2
|
+
const { getUsers, createUser, updateUser, deleteUser } = require('../controllers/userController');
|
|
3
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
4
|
+
const authMiddleware = require('../middleware/authMiddleware');
|
|
5
|
+
<%_ } _%>
|
|
6
|
+
|
|
7
|
+
const router = Router();
|
|
8
|
+
|
|
9
|
+
router.get('/users', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>getUsers);
|
|
10
|
+
router.post('/users', createUser);
|
|
11
|
+
router.patch('/users/:id', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>updateUser);
|
|
12
|
+
router.delete('/users/:id', <% if (auth.includes('JWT')) { %>authMiddleware, <% } %>deleteUser);
|
|
13
|
+
|
|
14
|
+
module.exports = router;
|
|
@@ -14,6 +14,9 @@ jest.mock('@/controllers/userController', () => ({
|
|
|
14
14
|
updateUser: (...args) => mockUpdateUser(...args),
|
|
15
15
|
deleteUser: (...args) => mockDeleteUser(...args)
|
|
16
16
|
}));
|
|
17
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
18
|
+
jest.mock('@/middleware/authMiddleware', () => (req, res, next) => next());
|
|
19
|
+
<%_ } _%>
|
|
17
20
|
|
|
18
21
|
describe('ApiRoutes', () => {
|
|
19
22
|
let app;
|
|
@@ -5,6 +5,7 @@ const ERROR_MESSAGES = {
|
|
|
5
5
|
INTERNAL_SERVER_ERROR: 'Internal Server Error',
|
|
6
6
|
BAD_REQUEST: 'Bad Request',
|
|
7
7
|
FETCH_USERS_ERROR: 'Error fetching users',
|
|
8
|
+
FETCH_USER_ERROR: 'Error fetching user',
|
|
8
9
|
CREATE_USER_ERROR: 'Error creating user',
|
|
9
10
|
UPDATE_USER_ERROR: 'Error updating user',
|
|
10
11
|
DELETE_USER_ERROR: 'Error deleting user',
|
|
@@ -33,13 +33,22 @@ const envSchema = z.object({
|
|
|
33
33
|
<%_ if (communication === 'Kafka') { -%>
|
|
34
34
|
KAFKA_BROKER: z.string(),
|
|
35
35
|
<%_ } -%>
|
|
36
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
37
|
+
JWT_SECRET: z.string(),
|
|
38
|
+
JWT_EXPIRES_IN: z.string().default('15m'),
|
|
39
|
+
JWT_REFRESH_SECRET: z.string().default('your-secret-refresh-key'),
|
|
40
|
+
JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),
|
|
41
|
+
<%_ } -%>
|
|
36
42
|
});
|
|
37
43
|
|
|
38
44
|
const _env = envSchema.safeParse(process.env);
|
|
39
45
|
|
|
40
46
|
if (!_env.success) {
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
48
|
+
logger.error('❌ Invalid environment variables:', _env.error.format());
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
logger.warn('⚠️ Environment validation failed. Continuing in test mode.');
|
|
43
52
|
}
|
|
44
53
|
|
|
45
|
-
export const env = _env.data
|
|
54
|
+
export const env = (_env.success ? _env.data : process.env) as unknown as z.infer<typeof envSchema>;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
<% if (communication !== 'GraphQL') { -%>
|
|
1
2
|
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
3
|
+
<% } -%>
|
|
4
|
+
<%_ if (communication === 'GraphQL') { _%>
|
|
2
5
|
import { ERROR_MESSAGES } from '@/utils/errorMessages';
|
|
6
|
+
<%_ } _%>
|
|
3
7
|
<% if (communication !== 'GraphQL') { -%>
|
|
4
8
|
import { Request, Response, NextFunction } from 'express';
|
|
5
9
|
<% } -%>
|
|
@@ -26,6 +30,12 @@ jest.mock('@/models/User', () => {
|
|
|
26
30
|
};
|
|
27
31
|
});
|
|
28
32
|
const User = require('@/models/User');
|
|
33
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
34
|
+
jest.mock('bcryptjs', () => ({
|
|
35
|
+
hash: jest.fn().mockResolvedValue('hashed_password'),
|
|
36
|
+
compare: jest.fn().mockResolvedValue(true)
|
|
37
|
+
}));
|
|
38
|
+
<%_ } _%>
|
|
29
39
|
<%_ if (caching === 'Redis') { -%>
|
|
30
40
|
jest.mock('@/config/redisClient', () => ({
|
|
31
41
|
getOrSet: jest.fn((_key, fetcher) => fetcher()),
|
|
@@ -179,7 +189,7 @@ describe('UserController', () => {
|
|
|
179
189
|
describe('createUser', () => {
|
|
180
190
|
it('should successfully create a new user (Happy Path)', async () => {
|
|
181
191
|
// Arrange
|
|
182
|
-
const payload = { name: 'Alice', email: 'alice@example.com' };
|
|
192
|
+
const payload = { name: 'Alice', email: 'alice@example.com'<% if (auth.includes('JWT')) { %>, password: 'password123'<% } %> };
|
|
183
193
|
<% if (communication === 'GraphQL') { -%>
|
|
184
194
|
const dataArg = payload;
|
|
185
195
|
<% } else { -%>
|
|
@@ -200,14 +210,21 @@ describe('UserController', () => {
|
|
|
200
210
|
const result = await userController.createUser(dataArg) as any;
|
|
201
211
|
|
|
202
212
|
// Assert
|
|
203
|
-
expect(result
|
|
213
|
+
expect(result!.password).toBeUndefined();
|
|
214
|
+
const { password, ...expectedUserWithoutPassword } = expectedUser as any;
|
|
215
|
+
expect(result!).toEqual(expectedUserWithoutPassword);
|
|
204
216
|
<% } else { -%>
|
|
205
217
|
await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
|
|
206
218
|
|
|
207
219
|
// Assert
|
|
208
220
|
expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
|
|
209
|
-
|
|
210
|
-
expect(
|
|
221
|
+
const { password: _, ...expectedUserWithoutPassword } = expectedUser as any;
|
|
222
|
+
expect(mockResponse.json).toHaveBeenCalledWith(expectedUserWithoutPassword);
|
|
223
|
+
expect(User.create).toHaveBeenCalledWith({
|
|
224
|
+
name: payload.name,
|
|
225
|
+
email: payload.email
|
|
226
|
+
<%_ if (auth.includes('JWT')) { _%>, password: 'hashed_password'<%_ } _%>
|
|
227
|
+
});
|
|
211
228
|
<% } -%>
|
|
212
229
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
213
230
|
expect(cacheService.del).toHaveBeenCalledWith('users:all');
|
|
@@ -217,10 +234,27 @@ describe('UserController', () => {
|
|
|
217
234
|
<%_ } -%>
|
|
218
235
|
});
|
|
219
236
|
|
|
237
|
+
<% if (auth.includes('JWT')) { %>
|
|
238
|
+
it('should throw error if password is missing when auth is enabled', async () => {
|
|
239
|
+
// Arrange
|
|
240
|
+
const payload = { name: 'Alice', email: 'alice@example.com' };
|
|
241
|
+
|
|
242
|
+
// Act & Assert
|
|
243
|
+
<% if (communication === 'GraphQL') { -%>
|
|
244
|
+
await expect(userController.createUser(payload as any)).rejects.toThrow('Password is required');
|
|
245
|
+
<% } else { -%>
|
|
246
|
+
mockRequest.body = payload;
|
|
247
|
+
await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
|
|
248
|
+
expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.BAD_REQUEST);
|
|
249
|
+
expect(mockResponse.json).toHaveBeenCalledWith({ error: 'Password is required' });
|
|
250
|
+
<% } -%>
|
|
251
|
+
});
|
|
252
|
+
<% } -%>
|
|
253
|
+
|
|
220
254
|
it('should handle errors when creation fails (Error Handling)', async () => {
|
|
221
255
|
// Arrange
|
|
222
256
|
const error = new Error('Creation Error');
|
|
223
|
-
const payload = { name: 'Bob', email: 'bob@example.com' };
|
|
257
|
+
const payload = { name: 'Bob', email: 'bob@example.com'<% if (auth.includes('JWT')) { %>, password: 'password123'<% } %> };
|
|
224
258
|
<% if (communication === 'GraphQL') { -%>
|
|
225
259
|
const dataArg = payload;
|
|
226
260
|
<% } else { -%>
|
|
@@ -445,9 +479,17 @@ describe('UserController', () => {
|
|
|
445
479
|
const error = new Error('Database Error');
|
|
446
480
|
(User.create as jest.Mock).mockRejectedValue(error);
|
|
447
481
|
<% if (communication === 'GraphQL') { -%>
|
|
448
|
-
await expect(userController.createUser({
|
|
482
|
+
await expect(userController.createUser({
|
|
483
|
+
name: 'Alice',
|
|
484
|
+
email: 'alice@example.com'
|
|
485
|
+
<%_ if (auth.includes('JWT')) { %>, password: 'password123' <%_ } %>
|
|
486
|
+
})).rejects.toThrow(error);
|
|
449
487
|
<% } else { -%>
|
|
450
|
-
mockRequest.body = {
|
|
488
|
+
mockRequest.body = {
|
|
489
|
+
name: 'Alice',
|
|
490
|
+
email: 'alice@example.com'
|
|
491
|
+
<%_ if (auth.includes('JWT')) { %>, password: 'password123' <%_ } %>
|
|
492
|
+
};
|
|
451
493
|
await userController.createUser(mockRequest as Request, mockResponse as Response, mockNext);
|
|
452
494
|
expect(mockNext).toHaveBeenCalledWith(error);
|
|
453
495
|
<% } -%>
|
|
@@ -475,6 +517,52 @@ describe('UserController', () => {
|
|
|
475
517
|
mockRequest.body = { name: 'Bob' };
|
|
476
518
|
await userController.updateUser(mockRequest as Request, mockResponse as Response, mockNext);
|
|
477
519
|
expect(mockNext).toHaveBeenCalledWith(error);
|
|
520
|
+
<% } -%>
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
|
|
524
|
+
describe('getUserById', () => {
|
|
525
|
+
it('should successfully fetch a user by id', async () => {
|
|
526
|
+
const id = '1';
|
|
527
|
+
const expectedUser = { id, name: 'Alice', email: 'alice@test.com' };
|
|
528
|
+
<% if (communication === 'GraphQL') { -%>
|
|
529
|
+
const idArg = id;
|
|
530
|
+
<% } else { -%>
|
|
531
|
+
mockRequest.params = { id };
|
|
532
|
+
<% } -%>
|
|
533
|
+
|
|
534
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
535
|
+
(User.findById as jest.Mock).mockResolvedValue(expectedUser);
|
|
536
|
+
<%_ } else if (database === 'None') { -%>
|
|
537
|
+
(User.findByPk as jest.Mock).mockResolvedValue(expectedUser);
|
|
538
|
+
<%_ } else { -%>
|
|
539
|
+
(User.findByPk as jest.Mock).mockResolvedValue(expectedUser);
|
|
540
|
+
<%_ } -%>
|
|
541
|
+
|
|
542
|
+
<% if (communication === 'GraphQL') { -%>
|
|
543
|
+
const result = await userController.getUserById(idArg);
|
|
544
|
+
expect(result).toEqual(expectedUser);
|
|
545
|
+
<% } else { -%>
|
|
546
|
+
await userController.getUserById(mockRequest as Request, mockResponse as Response, mockNext);
|
|
547
|
+
expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.OK);
|
|
548
|
+
expect(mockResponse.json).toHaveBeenCalledWith(expectedUser);
|
|
549
|
+
<% } -%>
|
|
550
|
+
});
|
|
551
|
+
|
|
552
|
+
it('should return 404 if user not found', async () => {
|
|
553
|
+
<% if (communication === 'GraphQL') { -%>
|
|
554
|
+
(User.findById as jest.Mock).mockResolvedValue(null);
|
|
555
|
+
(User.findByPk as jest.Mock).mockResolvedValue(null);
|
|
556
|
+
await expect(userController.getUserById('999')).rejects.toThrow();
|
|
557
|
+
<% } else { -%>
|
|
558
|
+
mockRequest.params = { id: '999' };
|
|
559
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
560
|
+
(User.findById as jest.Mock).mockResolvedValue(null);
|
|
561
|
+
<%_ } else { -%>
|
|
562
|
+
(User.findByPk as jest.Mock).mockResolvedValue(null);
|
|
563
|
+
<%_ } -%>
|
|
564
|
+
await userController.getUserById(mockRequest as Request, mockResponse as Response, mockNext);
|
|
565
|
+
expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.NOT_FOUND);
|
|
478
566
|
<% } -%>
|
|
479
567
|
});
|
|
480
568
|
});
|
|
@@ -12,6 +12,8 @@ import cacheService from '@/config/memoryCache';
|
|
|
12
12
|
<%_ } -%><%_ if (communication === 'Kafka') { -%>
|
|
13
13
|
import { kafkaService } from '@/services/kafkaService';
|
|
14
14
|
import { KAFKA_ACTIONS } from '@/utils/kafkaEvents';
|
|
15
|
+
<%_ } -%><%_ if (auth.includes('JWT')) { %>
|
|
16
|
+
import bcrypt from 'bcryptjs';
|
|
15
17
|
<%_ } -%>
|
|
16
18
|
|
|
17
19
|
export class UserController {
|
|
@@ -40,22 +42,47 @@ export class UserController {
|
|
|
40
42
|
}
|
|
41
43
|
}
|
|
42
44
|
|
|
43
|
-
async
|
|
45
|
+
async getUserById(id: string) {
|
|
44
46
|
try {
|
|
45
|
-
|
|
47
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
48
|
+
const user = await User.findById(id);
|
|
49
|
+
<%_ } else { -%>
|
|
50
|
+
const user = await User.findByPk(id);
|
|
51
|
+
<%_ } -%>
|
|
52
|
+
if (!user) throw new Error(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
53
|
+
return user;
|
|
54
|
+
} catch (error) {
|
|
55
|
+
logger.error(`${ERROR_MESSAGES.FETCH_USER_ERROR}:`, error);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async createUser(data: { name: string, email: string<% if (auth.includes('JWT')) { %>, password?: string<% } %> }) {
|
|
61
|
+
try {
|
|
62
|
+
const { name, email<% if (auth.includes('JWT')) { %>, password<% } %> } = data;
|
|
63
|
+
<% if (auth.includes('JWT')) { %>
|
|
64
|
+
if (!password) throw new Error('Password is required');
|
|
65
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
66
|
+
const user = await User.create({ name, email, password: hashedPassword });
|
|
67
|
+
<% } else { %>
|
|
46
68
|
const user = await User.create({ name, email });
|
|
69
|
+
<% } %>
|
|
70
|
+
|
|
47
71
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
48
72
|
await cacheService.del('users:all');
|
|
49
73
|
<%_ } -%>
|
|
50
74
|
<%_ if (communication === 'Kafka') { -%>
|
|
51
|
-
|
|
52
|
-
const userId =
|
|
75
|
+
const rawUserForKafka = user as unknown as { id?: string | number; _id?: string | number; email: string };
|
|
76
|
+
const userId = rawUserForKafka.id || rawUserForKafka._id;
|
|
53
77
|
await kafkaService.sendMessage('user-topic', JSON.stringify({
|
|
54
78
|
action: KAFKA_ACTIONS.USER_CREATED,
|
|
55
|
-
payload: { id: userId, email:
|
|
79
|
+
payload: { id: userId, email: rawUserForKafka.email }
|
|
56
80
|
}), userId?.toString() || '');
|
|
57
81
|
<%_ } -%>
|
|
58
|
-
|
|
82
|
+
const rawUser = user as unknown as { toJSON?: () => Record<string, unknown> };
|
|
83
|
+
const userJson = typeof rawUser.toJSON === 'function' ? rawUser.toJSON() : (user as unknown as Record<string, unknown>);
|
|
84
|
+
const { password: _, ...userWithoutPassword } = userJson;
|
|
85
|
+
return userWithoutPassword;
|
|
59
86
|
} catch (error) {
|
|
60
87
|
logger.error(`${ERROR_MESSAGES.CREATE_USER_ERROR}:`, error);
|
|
61
88
|
throw error;
|
|
@@ -147,22 +174,52 @@ export class UserController {
|
|
|
147
174
|
}
|
|
148
175
|
}
|
|
149
176
|
|
|
177
|
+
async getUserById(req: Request, res: Response, next: NextFunction) {
|
|
178
|
+
try {
|
|
179
|
+
const { id } = req.params;
|
|
180
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
181
|
+
const user = await User.findById(id);
|
|
182
|
+
<%_ } else { -%>
|
|
183
|
+
const user = await User.findByPk(id);
|
|
184
|
+
<%_ } -%>
|
|
185
|
+
if (!user) {
|
|
186
|
+
return res.status(HTTP_STATUS.NOT_FOUND).json({ error: ERROR_MESSAGES.USER_NOT_FOUND });
|
|
187
|
+
}
|
|
188
|
+
res.status(HTTP_STATUS.OK).json(user);
|
|
189
|
+
} catch (error) {
|
|
190
|
+
logger.error(`${ERROR_MESSAGES.FETCH_USER_ERROR}:`, error);
|
|
191
|
+
next(error);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
150
195
|
async createUser(req: Request, res: Response, next: NextFunction) {
|
|
151
196
|
try {
|
|
152
|
-
const { name, email } = req.body || {};
|
|
197
|
+
const { name, email, password } = req.body || {};
|
|
198
|
+
<% if (auth.includes('JWT')) { %>
|
|
199
|
+
if (!password) {
|
|
200
|
+
return res.status(HTTP_STATUS.BAD_REQUEST).json({ error: 'Password is required' });
|
|
201
|
+
}
|
|
202
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
203
|
+
const user = await User.create({ name, email, password: hashedPassword });
|
|
204
|
+
<% } else { %>
|
|
153
205
|
const user = await User.create({ name, email });
|
|
206
|
+
<% } %>
|
|
207
|
+
|
|
154
208
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
155
209
|
await cacheService.del('users:all');
|
|
156
210
|
<%_ } -%>
|
|
157
211
|
<%_ if (communication === 'Kafka') { -%>
|
|
158
|
-
|
|
159
|
-
const userId =
|
|
212
|
+
const rawUserForKafka = user as unknown as { id?: string | number; _id?: string | number; email: string };
|
|
213
|
+
const userId = rawUserForKafka.id || rawUserForKafka._id;
|
|
160
214
|
await kafkaService.sendMessage('user-topic', JSON.stringify({
|
|
161
215
|
action: KAFKA_ACTIONS.USER_CREATED,
|
|
162
|
-
payload: { id: userId, email:
|
|
216
|
+
payload: { id: userId, email: rawUserForKafka.email }
|
|
163
217
|
}), userId?.toString() || '');
|
|
164
218
|
<%_ } -%>
|
|
165
|
-
|
|
219
|
+
const rawUser = user as unknown as { toJSON?: () => Record<string, unknown> };
|
|
220
|
+
const userJson = typeof rawUser.toJSON === 'function' ? rawUser.toJSON() : (user as unknown as Record<string, unknown>);
|
|
221
|
+
const { password: _, ...userWithoutPassword } = userJson;
|
|
222
|
+
res.status(HTTP_STATUS.CREATED).json(userWithoutPassword);
|
|
166
223
|
} catch (error) {
|
|
167
224
|
logger.error('Error creating user:', error);
|
|
168
225
|
next(error);
|
|
@@ -1,30 +1,43 @@
|
|
|
1
|
-
import { gqlContext } from '@/graphql/context';
|
|
2
1
|
import { Request } from 'express';
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
<% if (auth.includes('JWT')) { %>import { JwtService } from '@/services/jwtService';
|
|
3
|
+
jest.mock('@/services/jwtService');<% } %>
|
|
4
|
+
import { gqlContext } from '@/graphql/context';
|
|
5
5
|
|
|
6
6
|
describe('GraphQL Context', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
jest.clearAllMocks();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('should return context with user when authorization header is present and valid', async () => {
|
|
12
|
+
<% if (auth.includes('JWT')) { %>
|
|
13
|
+
const mockUser = { id: '1', email: 'test@test.com' };
|
|
14
|
+
(JwtService.verifyToken as jest.Mock).mockReturnValue(mockUser);
|
|
15
|
+
const mockRequest = {
|
|
16
|
+
headers: {
|
|
17
|
+
authorization: 'Bearer valid-token',
|
|
18
|
+
},
|
|
19
|
+
} as Request;
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const context = await gqlContext({ req: mockRequest });
|
|
22
|
+
expect(context.user).toEqual(mockUser);
|
|
23
|
+
expect(JwtService.verifyToken).toHaveBeenCalledWith('valid-token');
|
|
24
|
+
<% } else { %>
|
|
25
|
+
const mockRequest = {
|
|
26
|
+
headers: {
|
|
27
|
+
authorization: 'Bearer token123',
|
|
28
|
+
},
|
|
29
|
+
} as Request;
|
|
30
|
+
const context = await gqlContext({ req: mockRequest });
|
|
31
|
+
expect(context.user).toBeUndefined();
|
|
32
|
+
<% } %>
|
|
33
|
+
});
|
|
21
34
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
35
|
+
it('should return empty context when authorization header is missing', async () => {
|
|
36
|
+
const mockRequest = {
|
|
37
|
+
headers: {},
|
|
38
|
+
} as Request;
|
|
26
39
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
40
|
+
const context = await gqlContext({ req: mockRequest });
|
|
41
|
+
expect(context.user).toBeUndefined();
|
|
42
|
+
});
|
|
30
43
|
});
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import { Request } from 'express';
|
|
2
|
+
<% if (auth.includes('JWT')) { %>import { JwtService } from '../services/jwtService';<% } %>
|
|
2
3
|
|
|
3
4
|
export interface MyContext {
|
|
4
|
-
token?: string;
|
|
5
|
-
|
|
5
|
+
token?: string; // Kept for backward compatibility
|
|
6
|
+
user?: unknown;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
|
-
export const gqlContext = async ({ req }: { req: Request }): Promise<MyContext> => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export const gqlContext = async ({ req: <% if (auth.includes('JWT')) { %>req<% } else { %>_req<% } %> }: { req: Request }): Promise<MyContext> => {
|
|
10
|
+
const context: MyContext = {};
|
|
11
|
+
<% if (auth.includes('JWT')) { %>
|
|
12
|
+
const authHeader = req.headers.authorization || '';
|
|
13
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
14
|
+
const token = authHeader.split(' ')[1];
|
|
15
|
+
const user = JwtService.verifyToken(token);
|
|
16
|
+
if (user) {
|
|
17
|
+
context.user = user;
|
|
18
|
+
}
|
|
19
|
+
}<% } %>
|
|
20
|
+
return context;
|
|
12
21
|
};
|
|
@@ -15,40 +15,62 @@ jest.mock('@/controllers/userController', () => {
|
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
describe('User Resolvers', () => {
|
|
18
|
+
const mockContext = {
|
|
19
|
+
<% if (auth.includes('JWT')) { %>user: { id: 'admin', email: 'admin@test.com' }<% } %>
|
|
20
|
+
};
|
|
21
|
+
|
|
18
22
|
afterEach(() => {
|
|
19
23
|
jest.clearAllMocks();
|
|
20
24
|
});
|
|
21
25
|
|
|
22
26
|
describe('Query.getAllUsers', () => {
|
|
23
|
-
it('should return all users', async () => {
|
|
24
|
-
const result = await userResolvers.Query.getAllUsers();
|
|
27
|
+
it('should return all users when authorized', async () => {
|
|
28
|
+
const result = await userResolvers.Query.getAllUsers(null, null, mockContext);
|
|
25
29
|
expect(result).toEqual([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
|
|
26
30
|
expect(mockGetUsers).toHaveBeenCalledTimes(1);
|
|
27
31
|
});
|
|
32
|
+
|
|
33
|
+
<% if (auth.includes('JWT')) { %>
|
|
34
|
+
it('should throw error when unauthorized', async () => {
|
|
35
|
+
await expect(userResolvers.Query.getAllUsers(null, null, {})).rejects.toThrow('Unauthorized');
|
|
36
|
+
});
|
|
37
|
+
<% } %>
|
|
28
38
|
});
|
|
29
39
|
|
|
30
40
|
describe('Mutation.createUser', () => {
|
|
31
|
-
it('should create and return a new user', async () => {
|
|
32
|
-
const
|
|
41
|
+
it('should create and return a new user (Public)', async () => {
|
|
42
|
+
const payload = { name: 'Jane', email: 'jane@example.com'<% if (auth.some(a => a !=='None')) { %>, password: 'password123'<% } %> };
|
|
43
|
+
const result = await userResolvers.Mutation.createUser(null, payload);
|
|
33
44
|
expect(result).toEqual({ id: '1', name: 'Jane', email: 'jane@example.com' });
|
|
34
|
-
expect(mockCreateUser).toHaveBeenCalledWith(
|
|
35
|
-
expect(mockCreateUser).toHaveBeenCalledTimes(1);
|
|
45
|
+
expect(mockCreateUser).toHaveBeenCalledWith(payload);
|
|
36
46
|
});
|
|
37
47
|
});
|
|
38
48
|
|
|
39
49
|
describe('Mutation.updateUser', () => {
|
|
40
|
-
it('should update and return the user', async () => {
|
|
50
|
+
it('should update and return the user when authorized', async () => {
|
|
41
51
|
const payload = { name: 'Updated' };
|
|
42
|
-
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload });
|
|
52
|
+
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload }, mockContext);
|
|
43
53
|
expect(result).toMatchObject(payload);
|
|
44
54
|
});
|
|
55
|
+
|
|
56
|
+
<% if (auth.includes('JWT')) { %>
|
|
57
|
+
it('should throw error when unauthorized', async () => {
|
|
58
|
+
await expect(userResolvers.Mutation.updateUser(null, { id: '1', name: 'N' }, {})).rejects.toThrow('Unauthorized');
|
|
59
|
+
});
|
|
60
|
+
<% } %>
|
|
45
61
|
});
|
|
46
62
|
|
|
47
63
|
describe('Mutation.deleteUser', () => {
|
|
48
|
-
it('should delete and return true', async () => {
|
|
49
|
-
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' });
|
|
64
|
+
it('should delete and return true when authorized', async () => {
|
|
65
|
+
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' }, mockContext);
|
|
50
66
|
expect(result).toBe(true);
|
|
51
67
|
});
|
|
68
|
+
|
|
69
|
+
<% if (auth.includes('JWT')) { %>
|
|
70
|
+
it('should throw error when unauthorized', async () => {
|
|
71
|
+
await expect(userResolvers.Mutation.deleteUser(null, { id: '1' }, {})).rejects.toThrow('Unauthorized');
|
|
72
|
+
});
|
|
73
|
+
<% } %>
|
|
52
74
|
});
|
|
53
75
|
<%_ if (database === 'MongoDB') { -%>
|
|
54
76
|
describe('User.id', () => {
|
|
@@ -1,24 +1,34 @@
|
|
|
1
1
|
import { UserController } from '@/controllers/userController';
|
|
2
|
+
import { MyContext } from '@/graphql/context';
|
|
2
3
|
|
|
3
4
|
const userController = new UserController();
|
|
4
5
|
|
|
5
6
|
export const userResolvers = {
|
|
6
7
|
Query: {
|
|
7
|
-
getAllUsers: async () => {
|
|
8
|
+
getAllUsers: async (_: unknown, __: unknown, <% if (auth.includes('JWT')) { %>context<% } else { %>_context<% } %>: MyContext) => {
|
|
9
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
10
|
+
if (!context.user) throw new Error('Unauthorized');
|
|
11
|
+
<%_ } -%>
|
|
8
12
|
const users = await userController.getUsers();
|
|
9
13
|
return users;
|
|
10
14
|
}
|
|
11
15
|
},
|
|
12
16
|
Mutation: {
|
|
13
|
-
createUser: async (_: unknown, { name, email }: { name: string, email: string }) => {
|
|
14
|
-
const user = await userController.createUser({ name, email });
|
|
17
|
+
createUser: async (_: unknown, { name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> }: { name: string, email: string<% if (auth.some(a => a !=='None')) { %>, password: string<% } %> }) => {
|
|
18
|
+
const user = await userController.createUser({ name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> });
|
|
15
19
|
return user;
|
|
16
20
|
},
|
|
17
|
-
updateUser: async (_: unknown, { id, name, email }: { id: string, name?: string, email?: string }) => {
|
|
21
|
+
updateUser: async (_: unknown, { id, name, email }: { id: string, name?: string, email?: string }, <% if (auth.includes('JWT')) { %>context<% } else { %>_context<% } %>: MyContext) => {
|
|
22
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
23
|
+
if (!context.user) throw new Error('Unauthorized');
|
|
24
|
+
<%_ } -%>
|
|
18
25
|
const user = await userController.updateUser(id, { name, email });
|
|
19
26
|
return user;
|
|
20
27
|
},
|
|
21
|
-
deleteUser: async (_: unknown, { id }: { id: string }) => {
|
|
28
|
+
deleteUser: async (_: unknown, { id }: { id: string }, <% if (auth.includes('JWT')) { %>context<% } else { %>_context<% } %>: MyContext) => {
|
|
29
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
30
|
+
if (!context.user) throw new Error('Unauthorized');
|
|
31
|
+
<%_ } -%>
|
|
22
32
|
const result = await userController.deleteUser(id);
|
|
23
33
|
return result;
|
|
24
34
|
}
|
|
@@ -10,7 +10,7 @@ export const userTypes = `#graphql
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
type Mutation {
|
|
13
|
-
createUser(name: String!, email: String
|
|
13
|
+
createUser(name: String!, email: String!<%_ if (auth.some(a => a !=='None')) { _%>, password: String!<%_ } _%>): User
|
|
14
14
|
updateUser(id: ID!, name: String, email: String): User
|
|
15
15
|
deleteUser(id: ID!): Boolean
|
|
16
16
|
}
|