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
|
@@ -0,0 +1,241 @@
|
|
|
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 Sign Up - <%= projectName %>
|
|
7
|
+
link(href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet")
|
|
8
|
+
style.
|
|
9
|
+
:root {
|
|
10
|
+
--primary: #22c55e;
|
|
11
|
+
--primary-glow: rgba(34, 197, 94, 0.4);
|
|
12
|
+
--bg-dark: #0f172a;
|
|
13
|
+
--card-bg: rgba(255, 255, 255, 0.03);
|
|
14
|
+
--card-border: rgba(255, 255, 255, 0.08);
|
|
15
|
+
--text-main: #f8fafc;
|
|
16
|
+
--text-muted: #94a3b8;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
* {
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: 0;
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
font-family: 'Poppins', sans-serif;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
body {
|
|
27
|
+
background-color: var(--bg-dark);
|
|
28
|
+
color: var(--text-main);
|
|
29
|
+
min-height: 100vh;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
overflow-x: hidden;
|
|
34
|
+
position: relative;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.background-blobs {
|
|
38
|
+
position: absolute;
|
|
39
|
+
width: 100%;
|
|
40
|
+
height: 100%;
|
|
41
|
+
z-index: -1;
|
|
42
|
+
filter: blur(80px);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.blob {
|
|
46
|
+
position: absolute;
|
|
47
|
+
width: 500px;
|
|
48
|
+
height: 500px;
|
|
49
|
+
border-radius: 50%;
|
|
50
|
+
opacity: 0.3;
|
|
51
|
+
animation: float 25s infinite alternate;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.blob-1 {
|
|
55
|
+
background: radial-gradient(circle, #22c55e 0%, transparent 70%);
|
|
56
|
+
top: -200px;
|
|
57
|
+
right: -100px;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.blob-2 {
|
|
61
|
+
background: radial-gradient(circle, #3b82f6 0%, transparent 70%);
|
|
62
|
+
bottom: -200px;
|
|
63
|
+
left: -100px;
|
|
64
|
+
animation-delay: -7s;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@keyframes float {
|
|
68
|
+
0% { transform: translate(0, 0) scale(1); }
|
|
69
|
+
100% { transform: translate(-150px, 100px) scale(1.3); }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.auth-card {
|
|
73
|
+
background: var(--card-bg);
|
|
74
|
+
backdrop-filter: blur(15px);
|
|
75
|
+
-webkit-backdrop-filter: blur(15px);
|
|
76
|
+
border: 1px solid var(--card-border);
|
|
77
|
+
border-radius: 28px;
|
|
78
|
+
padding: 48px;
|
|
79
|
+
width: 100%;
|
|
80
|
+
max-width: 480px;
|
|
81
|
+
box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.6);
|
|
82
|
+
z-index: 1;
|
|
83
|
+
margin: 40px 20px;
|
|
84
|
+
animation: fadeIn 0.8s ease-out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes fadeIn {
|
|
88
|
+
from { opacity: 0; transform: translateY(15px); }
|
|
89
|
+
to { opacity: 1; transform: translateY(0); }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.auth-card h2 {
|
|
93
|
+
font-size: 32px;
|
|
94
|
+
font-weight: 600;
|
|
95
|
+
margin-bottom: 8px;
|
|
96
|
+
text-align: center;
|
|
97
|
+
background: linear-gradient(to right, #fff, #94a3b8);
|
|
98
|
+
-webkit-background-clip: text;
|
|
99
|
+
-webkit-text-fill-color: transparent;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.subtitle {
|
|
103
|
+
text-align: center;
|
|
104
|
+
color: var(--text-muted);
|
|
105
|
+
font-size: 14px;
|
|
106
|
+
margin-bottom: 40px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.form-grid {
|
|
110
|
+
display: grid;
|
|
111
|
+
gap: 20px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.form-group label {
|
|
115
|
+
display: block;
|
|
116
|
+
margin-bottom: 8px;
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
font-weight: 500;
|
|
119
|
+
color: var(--text-muted);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.form-group input {
|
|
123
|
+
width: 100%;
|
|
124
|
+
background: rgba(255, 255, 255, 0.04);
|
|
125
|
+
border: 1px solid var(--card-border);
|
|
126
|
+
border-radius: 14px;
|
|
127
|
+
padding: 13px 18px;
|
|
128
|
+
color: #fff;
|
|
129
|
+
font-size: 15px;
|
|
130
|
+
transition: all 0.3s;
|
|
131
|
+
outline: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.form-group input:focus {
|
|
135
|
+
background: rgba(255, 255, 255, 0.07);
|
|
136
|
+
border-color: var(--primary);
|
|
137
|
+
box-shadow: 0 0 0 4px var(--primary-glow);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.btn-primary {
|
|
141
|
+
width: 100%;
|
|
142
|
+
background: var(--primary);
|
|
143
|
+
color: white;
|
|
144
|
+
border: none;
|
|
145
|
+
border-radius: 14px;
|
|
146
|
+
padding: 15px;
|
|
147
|
+
font-size: 16px;
|
|
148
|
+
font-weight: 600;
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
151
|
+
margin-top: 15px;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.btn-primary:hover {
|
|
155
|
+
transform: scale(1.02);
|
|
156
|
+
filter: brightness(1.1);
|
|
157
|
+
box-shadow: 0 15px 25px -5px rgba(34, 197, 94, 0.4);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.footer {
|
|
161
|
+
margin-top: 40px;
|
|
162
|
+
text-align: center;
|
|
163
|
+
font-size: 14px;
|
|
164
|
+
color: var(--text-muted);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.footer a {
|
|
168
|
+
color: var(--primary);
|
|
169
|
+
text-decoration: none;
|
|
170
|
+
font-weight: 600;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.back-home {
|
|
174
|
+
display: block;
|
|
175
|
+
margin-top: 20px;
|
|
176
|
+
font-size: 12px;
|
|
177
|
+
opacity: 0.5;
|
|
178
|
+
}
|
|
179
|
+
body
|
|
180
|
+
div.background-blobs
|
|
181
|
+
div.blob.blob-1
|
|
182
|
+
div.blob.blob-2
|
|
183
|
+
div.auth-card
|
|
184
|
+
h2 Join Us
|
|
185
|
+
p.subtitle Create your account in seconds
|
|
186
|
+
form.form-grid(action="/api/users" method="POST")
|
|
187
|
+
div.form-group
|
|
188
|
+
label(for="name") Full Name
|
|
189
|
+
input(type="text" id="name" name="name" placeholder="John Doe" required)
|
|
190
|
+
div.form-group
|
|
191
|
+
label(for="email") Email Address
|
|
192
|
+
input(type="email" id="email" name="email" placeholder="john@example.com" required)
|
|
193
|
+
div.form-group
|
|
194
|
+
label(for="password") Choose Password
|
|
195
|
+
input(type="password" id="password" name="password" placeholder="••••••••" required)
|
|
196
|
+
button.btn-primary(type="submit") Create Account
|
|
197
|
+
div.footer
|
|
198
|
+
p Already have an account?
|
|
199
|
+
a(href="/login") Sign in
|
|
200
|
+
a.back-home(href="/") ← Back to home
|
|
201
|
+
|
|
202
|
+
<% if (communication === 'GraphQL') { %>
|
|
203
|
+
script.
|
|
204
|
+
document.querySelector('form').addEventListener('submit', async (e) => {
|
|
205
|
+
e.preventDefault();
|
|
206
|
+
const formData = new FormData(e.target);
|
|
207
|
+
const data = Object.fromEntries(formData.entries());
|
|
208
|
+
|
|
209
|
+
const query = `
|
|
210
|
+
mutation CreateUser($name: String!, $email: String!, $password: String!) {
|
|
211
|
+
createUser(name: $name, email: $email, password: $password) {
|
|
212
|
+
id
|
|
213
|
+
name
|
|
214
|
+
email
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
const response = await fetch('/graphql', {
|
|
221
|
+
method: 'POST',
|
|
222
|
+
headers: { 'Content-Type': 'application/json' },
|
|
223
|
+
body: JSON.stringify({
|
|
224
|
+
query,
|
|
225
|
+
variables: data
|
|
226
|
+
})
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const result = await response.json();
|
|
230
|
+
if (result.errors) {
|
|
231
|
+
alert('Error: ' + result.errors[0].message);
|
|
232
|
+
} else {
|
|
233
|
+
alert('Account created successfully! Please login.');
|
|
234
|
+
window.location.href = '/login';
|
|
235
|
+
}
|
|
236
|
+
} catch (err) {
|
|
237
|
+
console.error(err);
|
|
238
|
+
alert('An error occurred during signup.');
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
<% } %>
|
|
@@ -2,9 +2,15 @@ CREATE TABLE users (
|
|
|
2
2
|
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
3
3
|
name VARCHAR(255) NOT NULL,
|
|
4
4
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
5
|
+
<% if (auth.includes('JWT')) { %>password VARCHAR(255) NOT NULL, <% } %>
|
|
5
6
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
6
7
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
7
8
|
deleted_at TIMESTAMP NULL
|
|
8
9
|
);
|
|
9
10
|
|
|
11
|
+
<% if (auth.includes('JWT')) { %>
|
|
12
|
+
INSERT INTO users (name, email, password) VALUES ('Admin User', 'admin@example.com', '$2a$10$X.fO9PeyF0Lq0lF8uV6G9u4Vb4e5T0rF8l/JzM6S7X9u4Vb4e5T0r'); -- password: password123
|
|
13
|
+
<% } else { %>
|
|
10
14
|
INSERT INTO users (name, email) VALUES ('Admin User', 'admin@example.com');
|
|
15
|
+
<% } %>
|
|
16
|
+
|
|
@@ -2,9 +2,15 @@ CREATE TABLE users (
|
|
|
2
2
|
id SERIAL PRIMARY KEY,
|
|
3
3
|
name VARCHAR(255) NOT NULL,
|
|
4
4
|
email VARCHAR(255) NOT NULL UNIQUE,
|
|
5
|
+
<% if (auth.includes('JWT')) { %>password VARCHAR(255) NOT NULL, <% } %>
|
|
5
6
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
6
7
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
7
8
|
deleted_at TIMESTAMP NULL
|
|
8
9
|
);
|
|
9
10
|
|
|
11
|
+
<% if (auth.includes('JWT')) { %>
|
|
12
|
+
INSERT INTO users (name, email, password) VALUES ('Admin User', 'admin@example.com', '$2a$10$X.fO9PeyF0Lq0lF8uV6G9u4Vb4e5T0rF8l/JzM6S7X9u4Vb4e5T0r'); -- password: password123
|
|
13
|
+
<% } else { %>
|
|
10
14
|
INSERT INTO users (name, email) VALUES ('Admin User', 'admin@example.com');
|
|
15
|
+
<% } %>
|
|
16
|
+
|
|
@@ -29,6 +29,12 @@ const envSchema = z.object({
|
|
|
29
29
|
REDIS_PORT: z.string().transform(Number),
|
|
30
30
|
REDIS_PASSWORD: z.string().optional(),
|
|
31
31
|
<%_ } -%>
|
|
32
|
+
<%_ if (auth.includes('JWT')) { -%>
|
|
33
|
+
JWT_SECRET: z.string(),
|
|
34
|
+
JWT_EXPIRES_IN: z.string().default('15m'),
|
|
35
|
+
JWT_REFRESH_SECRET: z.string().default('your-secret-refresh-key'),
|
|
36
|
+
JWT_REFRESH_EXPIRES_IN: z.string().default('7d'),
|
|
37
|
+
<%_ } -%>
|
|
32
38
|
<%_ if (communication === 'Kafka') { -%>
|
|
33
39
|
KAFKA_BROKER: z.string(),
|
|
34
40
|
<%_ } -%>
|
|
@@ -37,10 +43,13 @@ const envSchema = z.object({
|
|
|
37
43
|
const _env = envSchema.safeParse(process.env);
|
|
38
44
|
|
|
39
45
|
if (!_env.success) {
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
if (process.env.NODE_ENV !== 'test') {
|
|
47
|
+
logger.error('❌ Invalid environment variables:', _env.error.format());
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
logger.warn('⚠️ Environment validation failed. Continuing in test mode.');
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
const env = _env.data;
|
|
53
|
+
const env = _env.success ? _env.data : process.env;
|
|
45
54
|
|
|
46
55
|
module.exports = { env };
|
|
@@ -13,7 +13,7 @@ const cacheService = require('../config/memoryCache');
|
|
|
13
13
|
const { sendMessage } = require('../services/kafkaService');
|
|
14
14
|
const { KAFKA_ACTIONS } = require('../utils/kafkaEvents');
|
|
15
15
|
<%_ } -%>
|
|
16
|
-
|
|
16
|
+
<% if (auth.includes('JWT')) { %>const bcrypt = require('bcryptjs');<% } %>
|
|
17
17
|
<% if (communication === 'GraphQL') { -%>
|
|
18
18
|
const getUsers = async () => {
|
|
19
19
|
try {
|
|
@@ -41,8 +41,19 @@ const getUsers = async () => {
|
|
|
41
41
|
|
|
42
42
|
const createUser = async (data) => {
|
|
43
43
|
try {
|
|
44
|
-
const { name, email } = data;
|
|
44
|
+
const { name, email<% if (auth.includes('JWT')) { %>, password<% } %> } = data;
|
|
45
|
+
<% if (auth.includes('JWT')) { %>
|
|
46
|
+
let user;
|
|
47
|
+
if (password) {
|
|
48
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
49
|
+
user = await User.create({ name, email, password: hashedPassword });
|
|
50
|
+
} else {
|
|
51
|
+
user = await User.create({ name, email });
|
|
52
|
+
}
|
|
53
|
+
<% } else { %>
|
|
45
54
|
const user = await User.create({ name, email });
|
|
55
|
+
<% } %>
|
|
56
|
+
|
|
46
57
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
47
58
|
await cacheService.del('users:all');
|
|
48
59
|
<%_ } -%>
|
|
@@ -52,7 +63,9 @@ const createUser = async (data) => {
|
|
|
52
63
|
payload: { id: user.id || user._id, email: user.email }
|
|
53
64
|
}), (user.id || user._id).toString());
|
|
54
65
|
<%_ } -%>
|
|
55
|
-
|
|
66
|
+
const userObj = user.toJSON ? user.toJSON() : { ...user };
|
|
67
|
+
delete userObj.password;
|
|
68
|
+
return userObj;
|
|
56
69
|
} catch (error) {
|
|
57
70
|
logger.error(`${ERROR_MESSAGES.CREATE_USER_ERROR}:`, error);
|
|
58
71
|
throw error;
|
|
@@ -148,8 +161,17 @@ const getUsers = async (req, res, next) => {
|
|
|
148
161
|
|
|
149
162
|
const createUser = async (req, res, next) => {
|
|
150
163
|
try {
|
|
151
|
-
const { name, email } = req.body || {};
|
|
164
|
+
const { name, email, password } = req.body || {};
|
|
165
|
+
<% if (auth.includes('JWT')) { %>
|
|
166
|
+
if (!password) {
|
|
167
|
+
return res.status(HTTP_STATUS.BAD_REQUEST).json({ error: 'Password is required' });
|
|
168
|
+
}
|
|
169
|
+
const hashedPassword = await bcrypt.hash(password, 10);
|
|
170
|
+
const user = await User.create({ name, email, password: hashedPassword });
|
|
171
|
+
<% } else { %>
|
|
152
172
|
const user = await User.create({ name, email });
|
|
173
|
+
<% } %>
|
|
174
|
+
|
|
153
175
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
154
176
|
await cacheService.del('users:all');
|
|
155
177
|
<%_ } -%>
|
|
@@ -159,7 +181,9 @@ const createUser = async (req, res, next) => {
|
|
|
159
181
|
payload: { id: user.id || user._id, email: user.email }
|
|
160
182
|
}), (user.id || user._id).toString());
|
|
161
183
|
<%_ } -%>
|
|
162
|
-
|
|
184
|
+
const userObj = user.toJSON ? user.toJSON() : { ...user };
|
|
185
|
+
delete userObj.password;
|
|
186
|
+
res.status(HTTP_STATUS.CREATED).json(userObj);
|
|
163
187
|
} catch (error) {
|
|
164
188
|
logger.error(`${ERROR_MESSAGES.CREATE_USER_ERROR}:`, error);
|
|
165
189
|
next(error);
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
<% if (communication !== 'GraphQL') { -%>
|
|
1
2
|
const HTTP_STATUS = require('@/utils/httpCodes');
|
|
3
|
+
<% } -%>
|
|
4
|
+
<% if (communication === 'GraphQL') { -%>
|
|
2
5
|
const ERROR_MESSAGES = require('@/utils/errorMessages');
|
|
6
|
+
<% } -%>
|
|
3
7
|
<% if (communication !== 'GraphQL') { -%>
|
|
4
8
|
// Express-only imports would go here
|
|
5
9
|
<% } -%>
|
|
@@ -40,6 +44,11 @@ jest.mock('@/config/memoryCache', () => ({
|
|
|
40
44
|
}));
|
|
41
45
|
<%_ } -%>
|
|
42
46
|
jest.mock('@/utils/logger');
|
|
47
|
+
<%_ if (auth.includes('JWT')) { _%>
|
|
48
|
+
jest.mock('bcryptjs', () => ({
|
|
49
|
+
hash: jest.fn().mockResolvedValue('hashed_password')
|
|
50
|
+
}));
|
|
51
|
+
<%_ } _%>
|
|
43
52
|
<%_ if (communication === 'Kafka') { -%>
|
|
44
53
|
jest.mock('@/services/kafkaService', () => {
|
|
45
54
|
const mockSendMessage = jest.fn().mockResolvedValue(undefined);
|
|
@@ -166,7 +175,7 @@ describe('UserController', () => {
|
|
|
166
175
|
describe('createUser', () => {
|
|
167
176
|
it('should successfully create a new user (Happy Path)', async () => {
|
|
168
177
|
// Arrange
|
|
169
|
-
const payload = { name: 'Alice', email: 'alice@example.com' };
|
|
178
|
+
const payload = { name: 'Alice', email: 'alice@example.com', password: 'password123' };
|
|
170
179
|
<% if (communication === 'GraphQL') { -%>
|
|
171
180
|
const dataArg = payload;
|
|
172
181
|
<% } else { -%>
|
|
@@ -185,20 +194,26 @@ describe('UserController', () => {
|
|
|
185
194
|
const result = await createUser(dataArg);
|
|
186
195
|
|
|
187
196
|
// Assert
|
|
188
|
-
|
|
197
|
+
expect(result.password).toBeUndefined();
|
|
189
198
|
expect(result.name).toBe(payload.name);
|
|
190
199
|
expect(result.email).toBe(payload.email);
|
|
191
|
-
|
|
192
|
-
expect(
|
|
193
|
-
|
|
194
|
-
|
|
200
|
+
|
|
201
|
+
expect(User.create).toHaveBeenCalledWith({
|
|
202
|
+
name: payload.name,
|
|
203
|
+
email: payload.email
|
|
204
|
+
<%_ if (auth.includes('JWT')) { _%>, password: 'hashed_password'<%_ } _%>
|
|
205
|
+
});
|
|
195
206
|
<% } else { -%>
|
|
196
207
|
await createUser(mockRequest, mockResponse, mockNext);
|
|
197
208
|
|
|
198
209
|
// Assert
|
|
199
210
|
expect(mockResponse.status).toHaveBeenCalledWith(HTTP_STATUS.CREATED);
|
|
200
|
-
expect(mockResponse.json).toHaveBeenCalledWith(
|
|
201
|
-
expect(User.create).toHaveBeenCalledWith(
|
|
211
|
+
expect(mockResponse.json).toHaveBeenCalledWith(expect.not.objectContaining({ password: expect.anything() }));
|
|
212
|
+
expect(User.create).toHaveBeenCalledWith({
|
|
213
|
+
name: payload.name,
|
|
214
|
+
email: payload.email
|
|
215
|
+
<%_ if (auth.includes('JWT')) { _%>, password: 'hashed_password'<%_ } _%>
|
|
216
|
+
});
|
|
202
217
|
<%_ } -%>
|
|
203
218
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
204
219
|
expect(cacheService.del).toHaveBeenCalledWith('users:all');
|
|
@@ -211,7 +226,7 @@ describe('UserController', () => {
|
|
|
211
226
|
it('should handle errors when creation fails (Error Handling)', async () => {
|
|
212
227
|
// Arrange
|
|
213
228
|
const error = new Error('Creation Error');
|
|
214
|
-
const payload = { name: 'Bob', email: 'bob@example.com' };
|
|
229
|
+
const payload = { name: 'Bob', email: 'bob@example.com', password: 'password123' };
|
|
215
230
|
<% if (communication === 'GraphQL') { -%>
|
|
216
231
|
const dataArg = payload;
|
|
217
232
|
<% } else { -%>
|
|
@@ -232,7 +247,7 @@ describe('UserController', () => {
|
|
|
232
247
|
<%_ if (communication === 'Kafka') { -%>
|
|
233
248
|
it('should successfully create a new user with _id for Kafka (Happy Path)', async () => {
|
|
234
249
|
// Arrange
|
|
235
|
-
const payload = { name: 'Bob', email: 'bob@example.com' };
|
|
250
|
+
const payload = { name: 'Bob', email: 'bob@example.com', password: 'password123' };
|
|
236
251
|
<% if (communication === 'GraphQL') { -%>
|
|
237
252
|
const dataArg = payload;
|
|
238
253
|
<% } else { -%>
|
|
@@ -446,9 +461,9 @@ describe('UserController', () => {
|
|
|
446
461
|
const error = new Error('Database Error');
|
|
447
462
|
User.create.mockRejectedValue(error);
|
|
448
463
|
<% if (communication === 'GraphQL') { -%>
|
|
449
|
-
await expect(createUser({ name: 'Alice', email: 'alice@example.com' })).rejects.toThrow(error);
|
|
464
|
+
await expect(createUser({ name: 'Alice', email: 'alice@example.com'<% if (auth.includes('JWT')) { %>, password: 'password123'<% } %> })).rejects.toThrow(error);
|
|
450
465
|
<% } else { -%>
|
|
451
|
-
mockRequest.body = { name: 'Alice', email: 'alice@example.com' };
|
|
466
|
+
mockRequest.body = { name: 'Alice', email: 'alice@example.com', password: 'password123' };
|
|
452
467
|
await createUser(mockRequest, mockResponse, mockNext);
|
|
453
468
|
expect(mockNext).toHaveBeenCalledWith(error);
|
|
454
469
|
<% } -%>
|
|
@@ -1,7 +1,18 @@
|
|
|
1
|
+
<% if (auth.includes('JWT')) { %>const JwtService = require('../services/jwtService');<% } %>
|
|
2
|
+
|
|
1
3
|
const gqlContext = async ({ req }) => {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
4
|
+
const context = {};
|
|
5
|
+
<% if (auth.includes('JWT')) { %>
|
|
6
|
+
const authHeader = req.headers.authorization || '';
|
|
7
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
8
|
+
const token = authHeader.split(' ')[1];
|
|
9
|
+
const user = JwtService.verifyToken(token);
|
|
10
|
+
if (user) {
|
|
11
|
+
context.user = user;
|
|
12
|
+
}
|
|
13
|
+
}<% } %>
|
|
14
|
+
|
|
15
|
+
return context;
|
|
5
16
|
};
|
|
6
17
|
|
|
7
18
|
module.exports = { gqlContext };
|
|
@@ -1,29 +1,44 @@
|
|
|
1
|
+
<% if (auth.includes('JWT')) { %>const JwtService = require('@/services/jwtService');
|
|
2
|
+
jest.mock('@/services/jwtService');<% } %>
|
|
1
3
|
const { gqlContext } = require('@/graphql/context');
|
|
2
|
-
const { resolvers } = require('@/graphql/
|
|
3
|
-
const { typeDefs } = require('@/graphql/typeDefs');
|
|
4
|
+
const { resolvers } = require('@/graphql/index');
|
|
5
|
+
const { typeDefs } = require('@/graphql/typeDefs/index');
|
|
4
6
|
|
|
5
7
|
describe('GraphQL Context', () => {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
expect(typeDefs).toBeDefined();
|
|
8
|
+
afterEach(() => {
|
|
9
|
+
jest.clearAllMocks();
|
|
9
10
|
});
|
|
10
|
-
it('should return context with token when authorization header is present', async () => {
|
|
11
|
-
const mockRequest = {
|
|
12
|
-
headers: {
|
|
13
|
-
authorization: 'Bearer token123',
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
11
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
12
|
+
it('should return context with user when authorization header is present and valid', async () => {
|
|
13
|
+
<% if (auth.includes('JWT')) { %>
|
|
14
|
+
const mockUser = { id: '1', email: 'test@test.com' };
|
|
15
|
+
JwtService.verifyToken.mockReturnValue(mockUser);
|
|
16
|
+
const mockRequest = {
|
|
17
|
+
headers: {
|
|
18
|
+
authorization: 'Bearer valid-token',
|
|
19
|
+
},
|
|
20
|
+
};
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
const context = await gqlContext({ req: mockRequest });
|
|
23
|
+
expect(context.user).toEqual(mockUser);
|
|
24
|
+
expect(JwtService.verifyToken).toHaveBeenCalledWith('valid-token');
|
|
25
|
+
<% } else { %>
|
|
26
|
+
const mockRequest = {
|
|
27
|
+
headers: {
|
|
28
|
+
authorization: 'Bearer token123',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
const context = await gqlContext({ req: mockRequest });
|
|
32
|
+
expect(context).toEqual({});
|
|
33
|
+
<% } %>
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should return empty context when authorization header is missing', async () => {
|
|
37
|
+
const mockRequest = {
|
|
38
|
+
headers: {},
|
|
39
|
+
};
|
|
25
40
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
41
|
+
const context = await gqlContext({ req: mockRequest });
|
|
42
|
+
expect(context).toEqual({});
|
|
43
|
+
});
|
|
29
44
|
});
|
|
@@ -2,18 +2,23 @@ const userController = require('../../controllers/userController');
|
|
|
2
2
|
|
|
3
3
|
const userResolvers = {
|
|
4
4
|
Query: {
|
|
5
|
-
getAllUsers: async () => {
|
|
5
|
+
getAllUsers: async (_, __, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
6
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
6
7
|
return await userController.getUsers();
|
|
7
8
|
}
|
|
8
9
|
},
|
|
9
10
|
Mutation: {
|
|
10
|
-
createUser: async (_, { name, email }) => {
|
|
11
|
-
|
|
11
|
+
createUser: async (_, { name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> }) => {
|
|
12
|
+
// Create user is typically public for registration
|
|
13
|
+
const user = await userController.createUser({ name, email<% if (auth.some(a => a !=='None')) { %>, password<% } %> });
|
|
14
|
+
return user;
|
|
12
15
|
},
|
|
13
|
-
updateUser: async (_, { id, name, email }) => {
|
|
16
|
+
updateUser: async (_, { id, name, email }, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
17
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
14
18
|
return await userController.updateUser(id, { name, email });
|
|
15
19
|
},
|
|
16
|
-
deleteUser: async (_, { id }) => {
|
|
20
|
+
deleteUser: async (_, { id }, <% if (auth.includes('JWT')) { %>{ user }<% } else { %>_context<% } %>) => {
|
|
21
|
+
<% if (auth.includes('JWT')) { %>if (!user) throw new Error('Unauthorized');<% } %>
|
|
17
22
|
return await userController.deleteUser(id);
|
|
18
23
|
}
|
|
19
24
|
}<%_ if (database === 'MongoDB') { -%>,
|
|
@@ -11,40 +11,62 @@ jest.mock('@/controllers/userController', () => ({
|
|
|
11
11
|
}));
|
|
12
12
|
|
|
13
13
|
describe('User Resolvers', () => {
|
|
14
|
+
const mockContext = {
|
|
15
|
+
<% if (auth.includes('JWT')) { %>user: { id: 'admin', email: 'admin@test.com' }<% } %>
|
|
16
|
+
};
|
|
17
|
+
|
|
14
18
|
afterEach(() => {
|
|
15
19
|
jest.clearAllMocks();
|
|
16
20
|
});
|
|
17
21
|
|
|
18
22
|
describe('Query.getAllUsers', () => {
|
|
19
|
-
it('should return all users', async () => {
|
|
20
|
-
const result = await userResolvers.Query.getAllUsers();
|
|
23
|
+
it('should return all users when authorized', async () => {
|
|
24
|
+
const result = await userResolvers.Query.getAllUsers(null, null, mockContext);
|
|
21
25
|
expect(result).toEqual([{ id: '1', name: 'John Doe', email: 'john@example.com' }]);
|
|
22
26
|
expect(mockGetUsers).toHaveBeenCalledTimes(1);
|
|
23
27
|
});
|
|
28
|
+
|
|
29
|
+
<% if (auth.includes('JWT')) { %>
|
|
30
|
+
it('should throw error when unauthorized', async () => {
|
|
31
|
+
await expect(userResolvers.Query.getAllUsers(null, null, {})).rejects.toThrow('Unauthorized');
|
|
32
|
+
});
|
|
33
|
+
<% } %>
|
|
24
34
|
});
|
|
25
35
|
|
|
26
36
|
describe('Mutation.createUser', () => {
|
|
27
|
-
it('should create and return a new user', async () => {
|
|
28
|
-
const
|
|
37
|
+
it('should create and return a new user (Public)', async () => {
|
|
38
|
+
const payload = { name: 'Jane', email: 'jane@example.com'<% if (auth.some(a => a !=='None')) { %>, password: 'password123'<% } %> };
|
|
39
|
+
const result = await userResolvers.Mutation.createUser(null, payload);
|
|
29
40
|
expect(result).toEqual({ id: '1', name: 'Jane', email: 'jane@example.com' });
|
|
30
|
-
expect(mockCreateUser).toHaveBeenCalledWith(
|
|
31
|
-
expect(mockCreateUser).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(mockCreateUser).toHaveBeenCalledWith(payload);
|
|
32
42
|
});
|
|
33
43
|
});
|
|
34
44
|
|
|
35
45
|
describe('Mutation.updateUser', () => {
|
|
36
|
-
it('should update and return the user', async () => {
|
|
46
|
+
it('should update and return the user when authorized', async () => {
|
|
37
47
|
const payload = { name: 'Updated' };
|
|
38
|
-
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload });
|
|
48
|
+
const result = await userResolvers.Mutation.updateUser(null, { id: '1', ...payload }, mockContext);
|
|
39
49
|
expect(result).toMatchObject(payload);
|
|
40
50
|
});
|
|
51
|
+
|
|
52
|
+
<% if (auth.includes('JWT')) { %>
|
|
53
|
+
it('should throw error when unauthorized', async () => {
|
|
54
|
+
await expect(userResolvers.Mutation.updateUser(null, { id: '1', name: 'N' }, {})).rejects.toThrow('Unauthorized');
|
|
55
|
+
});
|
|
56
|
+
<% } %>
|
|
41
57
|
});
|
|
42
58
|
|
|
43
59
|
describe('Mutation.deleteUser', () => {
|
|
44
|
-
it('should delete and return true', async () => {
|
|
45
|
-
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' });
|
|
60
|
+
it('should delete and return true when authorized', async () => {
|
|
61
|
+
const result = await userResolvers.Mutation.deleteUser(null, { id: '1' }, mockContext);
|
|
46
62
|
expect(result).toBe(true);
|
|
47
63
|
});
|
|
64
|
+
|
|
65
|
+
<% if (auth.includes('JWT')) { %>
|
|
66
|
+
it('should throw error when unauthorized', async () => {
|
|
67
|
+
await expect(userResolvers.Mutation.deleteUser(null, { id: '1' }, {})).rejects.toThrow('Unauthorized');
|
|
68
|
+
});
|
|
69
|
+
<% } %>
|
|
48
70
|
});
|
|
49
71
|
<%_ if (database === 'MongoDB') { -%>
|
|
50
72
|
describe('User.id', () => {
|
|
@@ -10,7 +10,7 @@ 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
|
}
|