@anthonylzq/simba.js 1.9.1 → 2.0.2
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/README.md +55 -27
- package/lib/index.js +1 -1
- package/lib/src/functions/docker.js +2 -2
- package/lib/src/functions/eslint.js +1 -1
- package/lib/src/functions/express.js +458 -350
- package/lib/src/functions/tsconfig.js +38 -8
- package/lib/src/installation.js +1 -3
- package/package.json +8 -4
- package/CHANGELOG.md +0 -124
|
@@ -5,30 +5,39 @@ const writeFile = require('../utils/writeFile')
|
|
|
5
5
|
/*
|
|
6
6
|
* src
|
|
7
7
|
* |- @types:
|
|
8
|
-
*
|
|
9
|
-
* |-
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* | | | |- user: content, file
|
|
13
|
-
* | | | |- index: content, file
|
|
14
|
-
* | | |- index: content, file
|
|
15
|
-
* | |- user: content, file
|
|
8
|
+
* |- |- dto:
|
|
9
|
+
* |- |- |- user: content, file
|
|
10
|
+
* |- |- models:
|
|
11
|
+
* |- |- |- user: content, file
|
|
16
12
|
* | |- index: content, file
|
|
17
|
-
* |-
|
|
18
|
-
* | |-
|
|
19
|
-
* | |-
|
|
20
|
-
* |-
|
|
21
|
-
* | |- user: content, file
|
|
13
|
+
* |- database:
|
|
14
|
+
* | |- mongo:
|
|
15
|
+
* | |- |- models:
|
|
16
|
+
* | |- |- |- index: content, file
|
|
17
|
+
* | |- |- |- user: content, file
|
|
18
|
+
* | |- |- queries:
|
|
19
|
+
* | |- |- |- index: content, file
|
|
20
|
+
* | |- |- |- user: content, file
|
|
21
|
+
* | |- |- index: content, file
|
|
22
22
|
* | |- index: content, file
|
|
23
23
|
* |- network:
|
|
24
|
+
* | |- routes:
|
|
25
|
+
* | | |- schemas:
|
|
26
|
+
* | | | |- user: content, file
|
|
27
|
+
* | | | |- index: content, file
|
|
28
|
+
* | | |- home: content, file
|
|
29
|
+
* | | |- user: content, file
|
|
30
|
+
* | | |- index: content, file
|
|
31
|
+
* | | |- response: content, file
|
|
32
|
+
* | |- router: content, file
|
|
24
33
|
* | |- server: content, file
|
|
25
|
-
* | |- routes: content, file
|
|
26
34
|
* | |- index: content, file
|
|
27
|
-
* |-
|
|
28
|
-
* | |-
|
|
29
|
-
* | |-
|
|
30
|
-
* | |-
|
|
31
|
-
* |-
|
|
35
|
+
* |- services:
|
|
36
|
+
* | |- utils:
|
|
37
|
+
* | | |- messages:
|
|
38
|
+
* | | | |- user: content, file
|
|
39
|
+
* | | | |- index: content, file
|
|
40
|
+
* | | |- index: content, file
|
|
32
41
|
* | |- user: content, file
|
|
33
42
|
* | |- index: content, file
|
|
34
43
|
* |- test:
|
|
@@ -50,265 +59,86 @@ module.exports = async (projectName, projectVersion, email) => {
|
|
|
50
59
|
'@types': {
|
|
51
60
|
index: {
|
|
52
61
|
content: `/* eslint-disable no-var */
|
|
53
|
-
|
|
54
|
-
import { Request, Response } from 'express'
|
|
55
|
-
|
|
56
|
-
import { DtoUser } from 'dto-interfaces'
|
|
57
|
-
|
|
58
|
-
declare global {
|
|
59
|
-
// This variable is global, so it will be available everywhere in the code
|
|
60
|
-
var response = (
|
|
61
|
-
error: boolean,
|
|
62
|
-
message: unknown,
|
|
63
|
-
res: Response,
|
|
64
|
-
status: number
|
|
65
|
-
): void => {
|
|
66
|
-
res.status(status).send({ error, message })
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// We can personalize the response and request objects in case we need it by
|
|
70
|
-
// adding new optional attributes to this interface
|
|
71
|
-
interface CustomResponse extends Response {
|
|
72
|
-
newValue?: string
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
interface CustomRequest extends Request {
|
|
76
|
-
body: {
|
|
77
|
-
args?: DtoUser
|
|
78
|
-
}
|
|
79
|
-
// We can add custom headers via intersection, remember that for some reason
|
|
80
|
-
// headers must be in Snake-Pascal-Case
|
|
81
|
-
headers: IncomingHttpHeaders & {
|
|
82
|
-
'Custom-Header'?: string
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}
|
|
62
|
+
declare global {}
|
|
86
63
|
|
|
87
64
|
export {}
|
|
88
65
|
`,
|
|
89
66
|
file: `${projectName}/src/@types/index.d.ts`
|
|
90
67
|
}
|
|
91
68
|
},
|
|
92
|
-
|
|
93
|
-
index: {
|
|
94
|
-
content: `import { User } from './user'
|
|
95
|
-
|
|
96
|
-
export { User }
|
|
97
|
-
`,
|
|
98
|
-
file: `${projectName}/src/controllers/index.ts`
|
|
99
|
-
},
|
|
69
|
+
'@types/dto': {
|
|
100
70
|
user: {
|
|
101
|
-
content: `
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
import { EFU, MFU, GE, errorHandling } from './utils'
|
|
106
|
-
|
|
107
|
-
type Process = {
|
|
108
|
-
type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
|
|
71
|
+
content: `interface DtoUser {
|
|
72
|
+
id?: string
|
|
73
|
+
lastName?: string
|
|
74
|
+
name?: string
|
|
109
75
|
}
|
|
76
|
+
`,
|
|
77
|
+
file: `${projectName}/src/@types/dto/user.d.ts`
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
'@types/custom': {
|
|
81
|
+
request: {
|
|
82
|
+
content: `type ExpressRequest = import('express').Request
|
|
110
83
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
constructor(args: DtoUser | null = null) {
|
|
115
|
-
this._args = args
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
public process({
|
|
119
|
-
type
|
|
120
|
-
}: Process): Promise<string> | Promise<IUser[]> | Promise<IUser> {
|
|
121
|
-
switch (type) {
|
|
122
|
-
case 'store':
|
|
123
|
-
return this._store()
|
|
124
|
-
case 'getAll':
|
|
125
|
-
return this._getAll()
|
|
126
|
-
case 'deleteAll':
|
|
127
|
-
return this._deleteAll()
|
|
128
|
-
case 'getOne':
|
|
129
|
-
return this._getOne()
|
|
130
|
-
case 'update':
|
|
131
|
-
return this._update()
|
|
132
|
-
case 'delete':
|
|
133
|
-
return this._delete()
|
|
134
|
-
default:
|
|
135
|
-
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private async _store(): Promise<IUser> {
|
|
140
|
-
const { lastName, name } = this._args as DtoUser
|
|
141
|
-
|
|
142
|
-
try {
|
|
143
|
-
const newUser = new UserModel({ lastName, name })
|
|
144
|
-
const result = await newUser.save()
|
|
145
|
-
|
|
146
|
-
return result
|
|
147
|
-
} catch (e) {
|
|
148
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
private async _getAll(): Promise<IUser[]> {
|
|
153
|
-
try {
|
|
154
|
-
const users = await UserModel.find({})
|
|
155
|
-
|
|
156
|
-
return users
|
|
157
|
-
} catch (e) {
|
|
158
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
private async _deleteAll(): Promise<string> {
|
|
163
|
-
try {
|
|
164
|
-
const usersDeleted = await UserModel.deleteMany({})
|
|
165
|
-
|
|
166
|
-
if (usersDeleted.acknowledged) return MFU.ALL_USERS_DELETED
|
|
167
|
-
|
|
168
|
-
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
169
|
-
} catch (e) {
|
|
170
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
private async _getOne(): Promise<IUser> {
|
|
175
|
-
const { id } = this._args as DtoUser
|
|
176
|
-
|
|
177
|
-
try {
|
|
178
|
-
const user = await UserModel.findById(id)
|
|
179
|
-
|
|
180
|
-
if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
181
|
-
|
|
182
|
-
return user
|
|
183
|
-
} catch (e) {
|
|
184
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
private async _update(): Promise<IUser> {
|
|
189
|
-
const { id, lastName, name } = this._args as DtoUser
|
|
190
|
-
|
|
191
|
-
try {
|
|
192
|
-
const updatedUser = await UserModel.findByIdAndUpdate(
|
|
193
|
-
id,
|
|
194
|
-
{ lastName, name },
|
|
195
|
-
{ new: true }
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
199
|
-
|
|
200
|
-
return updatedUser
|
|
201
|
-
} catch (e) {
|
|
202
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
203
|
-
}
|
|
84
|
+
interface CustomRequest extends ExpressRequest {
|
|
85
|
+
body: {
|
|
86
|
+
args?: DtoUser
|
|
204
87
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
try {
|
|
210
|
-
const deletedUser = await UserModel.findByIdAndRemove(id)
|
|
211
|
-
|
|
212
|
-
if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
213
|
-
|
|
214
|
-
return MFU.USER_DELETED
|
|
215
|
-
} catch (e) {
|
|
216
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
217
|
-
}
|
|
88
|
+
// We can add custom headers via intersection, remember that for some reason
|
|
89
|
+
// headers must be in Snake-Pascal-Case
|
|
90
|
+
headers: import('http').IncomingHttpHeaders & {
|
|
91
|
+
'Custom-Header'?: string
|
|
218
92
|
}
|
|
219
93
|
}
|
|
220
|
-
|
|
221
|
-
export { User }
|
|
222
94
|
`,
|
|
223
|
-
file: `${projectName}/src/
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
index: {
|
|
228
|
-
content: `import httpErrors from 'http-errors'
|
|
229
|
-
|
|
230
|
-
import { EFU, MFU, GE } from './messages'
|
|
231
|
-
|
|
232
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
233
|
-
const errorHandling = (e: any, message?: string): never => {
|
|
234
|
-
console.error(e)
|
|
235
|
-
|
|
236
|
-
if (e instanceof httpErrors.HttpError) throw e
|
|
95
|
+
file: `${projectName}/src/@types/custom/request.d.ts`
|
|
96
|
+
},
|
|
97
|
+
response: {
|
|
98
|
+
content: `type ExpressResponse = import('express').Response
|
|
237
99
|
|
|
238
|
-
|
|
100
|
+
interface CustomResponse extends ExpressResponse {
|
|
101
|
+
newValue?: string
|
|
239
102
|
}
|
|
240
|
-
|
|
241
|
-
export { EFU, MFU, GE, errorHandling }
|
|
242
103
|
`,
|
|
243
|
-
file: `${projectName}/src/
|
|
104
|
+
file: `${projectName}/src/@types/custom/response.d.ts`
|
|
244
105
|
}
|
|
245
106
|
},
|
|
246
|
-
'
|
|
247
|
-
index: {
|
|
248
|
-
content: `import { EFU, MFU } from './user'
|
|
249
|
-
|
|
250
|
-
enum GenericErrors {
|
|
251
|
-
INTERNAL_SERVER_ERROR = 'Something went wrong'
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
export { EFU, MFU, GenericErrors as GE }
|
|
255
|
-
`,
|
|
256
|
-
file: `${projectName}/src/controllers/utils/messages/index.ts`
|
|
257
|
-
},
|
|
107
|
+
'@types/models': {
|
|
258
108
|
user: {
|
|
259
|
-
content: `
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
ALL_USERS_DELETED = 'All the users were deleted successfully',
|
|
265
|
-
USER_DELETED = 'The requested user was successfully deleted'
|
|
109
|
+
content: `interface IUser {
|
|
110
|
+
_id: import('mongoose').Types.ObjectId
|
|
111
|
+
name: string
|
|
112
|
+
lastName: string
|
|
113
|
+
updatedAt: Date
|
|
266
114
|
}
|
|
267
|
-
|
|
268
|
-
export { ErrorForUser as EFU, MessageForUser as MFU }
|
|
269
115
|
`,
|
|
270
|
-
file: `${projectName}/src/
|
|
116
|
+
file: `${projectName}/src/@types/models/user.d.ts`
|
|
271
117
|
}
|
|
272
118
|
},
|
|
273
|
-
|
|
119
|
+
database: {
|
|
274
120
|
index: {
|
|
275
|
-
content:
|
|
276
|
-
|
|
277
|
-
export { DtoUser }
|
|
278
|
-
`,
|
|
279
|
-
file: `${projectName}/src/dto-interfaces/index.ts`
|
|
280
|
-
},
|
|
281
|
-
user: {
|
|
282
|
-
content: `interface DtoUser {
|
|
283
|
-
id: string
|
|
284
|
-
lastName?: string
|
|
285
|
-
name?: string
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
export { DtoUser }
|
|
289
|
-
`,
|
|
290
|
-
file: `${projectName}/src/dto-interfaces/user.ts`
|
|
121
|
+
content: "export * from './mongo'\n",
|
|
122
|
+
file: `${projectName}/src/database/index.ts`
|
|
291
123
|
}
|
|
292
124
|
},
|
|
293
|
-
|
|
125
|
+
'database/mongo': {
|
|
294
126
|
index: {
|
|
295
|
-
content: `
|
|
296
|
-
|
|
297
|
-
export { IUser, UserModel }
|
|
127
|
+
content: `export * from './models'
|
|
128
|
+
export * from './queries'
|
|
298
129
|
`,
|
|
299
|
-
file: `${projectName}/src/
|
|
130
|
+
file: `${projectName}/src/database/mongo/index.ts`
|
|
131
|
+
}
|
|
132
|
+
},
|
|
133
|
+
'database/mongo/models': {
|
|
134
|
+
index: {
|
|
135
|
+
content: "export * from './user'\n",
|
|
136
|
+
file: `${projectName}/src/database/mongo/models/index.ts`
|
|
300
137
|
},
|
|
301
138
|
user: {
|
|
302
|
-
content:
|
|
303
|
-
import { Document, model, Schema } from 'mongoose'
|
|
139
|
+
content: `import { model, Schema } from 'mongoose'
|
|
304
140
|
|
|
305
|
-
|
|
306
|
-
lastName: string
|
|
307
|
-
name: string
|
|
308
|
-
updatedAt: Date
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
const User = new Schema(
|
|
141
|
+
const User = new Schema<IUser>(
|
|
312
142
|
{
|
|
313
143
|
lastName: {
|
|
314
144
|
required: true,
|
|
@@ -323,36 +153,98 @@ const User = new Schema(
|
|
|
323
153
|
timestamps: {
|
|
324
154
|
createdAt: false,
|
|
325
155
|
updatedAt: true
|
|
156
|
+
},
|
|
157
|
+
toJSON: {
|
|
158
|
+
transform(_, ret) {
|
|
159
|
+
ret.id = ret._id
|
|
160
|
+
delete ret._id
|
|
161
|
+
delete ret.__v
|
|
162
|
+
delete ret.updatedAt
|
|
163
|
+
},
|
|
164
|
+
versionKey: false,
|
|
165
|
+
virtuals: true
|
|
326
166
|
}
|
|
327
167
|
}
|
|
328
168
|
)
|
|
329
169
|
|
|
330
|
-
User.set('toJSON', {
|
|
331
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
332
|
-
transform: function (_: any, ret: any) {
|
|
333
|
-
ret.id = ret._id
|
|
334
|
-
delete ret._id
|
|
335
|
-
delete ret.__v
|
|
336
|
-
delete ret.updatedAt
|
|
337
|
-
},
|
|
338
|
-
versionKey: false,
|
|
339
|
-
virtuals: true
|
|
340
|
-
})
|
|
341
|
-
|
|
342
170
|
const UserModel = model<IUser>('users', User)
|
|
343
171
|
|
|
344
|
-
export {
|
|
172
|
+
export { UserModel }
|
|
345
173
|
`,
|
|
346
|
-
file: `${projectName}/src/models/user.ts`
|
|
174
|
+
file: `${projectName}/src/database/mongo/models/user.ts`
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
'database/mongo/queries': {
|
|
178
|
+
index: {
|
|
179
|
+
content: "export * from './user'\n",
|
|
180
|
+
file: `${projectName}/src/database/mongo/queries/index.ts`
|
|
181
|
+
},
|
|
182
|
+
user: {
|
|
183
|
+
content: `import { UserModel } from '../models'
|
|
184
|
+
|
|
185
|
+
const store = async (userData: DtoUser): Promise<IUser> => {
|
|
186
|
+
const user = new UserModel(userData)
|
|
187
|
+
|
|
188
|
+
return await user.save()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const remove = async (
|
|
192
|
+
id: string | null = null
|
|
193
|
+
): Promise<IUser | number | null> => {
|
|
194
|
+
if (id) return await UserModel.findByIdAndRemove(id)
|
|
195
|
+
|
|
196
|
+
return (await UserModel.deleteMany({})).deletedCount
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const get = async (
|
|
200
|
+
id: string | null = null
|
|
201
|
+
): Promise<IUser[] | IUser | null> => {
|
|
202
|
+
if (id) return await UserModel.findById(id)
|
|
203
|
+
|
|
204
|
+
return await UserModel.find({})
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const update = async (userData: DtoUser): Promise<IUser | null> => {
|
|
208
|
+
const { id, ...rest } = userData
|
|
209
|
+
|
|
210
|
+
return await UserModel.findByIdAndUpdate(id, rest, { new: true })
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export { store, remove, get, update }
|
|
214
|
+
`,
|
|
215
|
+
file: `${projectName}/src/database/mongo/queries/user.ts`
|
|
347
216
|
}
|
|
348
217
|
},
|
|
349
218
|
network: {
|
|
350
|
-
|
|
219
|
+
index: {
|
|
220
|
+
content: `export * from './routes'
|
|
221
|
+
export * from './server'
|
|
222
|
+
`,
|
|
223
|
+
file: `${projectName}/src/network/index.ts`
|
|
224
|
+
},
|
|
225
|
+
response: {
|
|
226
|
+
content: `interface ResponseProps {
|
|
227
|
+
error: boolean
|
|
228
|
+
message: unknown
|
|
229
|
+
res: CustomResponse
|
|
230
|
+
status: number
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
const response = ({ error, message, res, status }: ResponseProps): void => {
|
|
234
|
+
res.status(status).send({ error, message })
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export { response }
|
|
238
|
+
`,
|
|
239
|
+
file: `${projectName}/src/network/response.ts`
|
|
240
|
+
},
|
|
241
|
+
router: {
|
|
351
242
|
content: `import { Application, Response, Request, Router, NextFunction } from 'express'
|
|
352
243
|
import swaggerUi from 'swagger-ui-express'
|
|
353
244
|
import httpErrors from 'http-errors'
|
|
354
245
|
|
|
355
|
-
import {
|
|
246
|
+
import { response } from './response'
|
|
247
|
+
import { Home, User } from './routes'
|
|
356
248
|
import { docs } from 'utils'
|
|
357
249
|
|
|
358
250
|
const routers = [User]
|
|
@@ -373,7 +265,12 @@ const applyRoutes = (app: Application): void => {
|
|
|
373
265
|
res: Response,
|
|
374
266
|
next: NextFunction
|
|
375
267
|
) => {
|
|
376
|
-
response(
|
|
268
|
+
response({
|
|
269
|
+
error: true,
|
|
270
|
+
message: error.message,
|
|
271
|
+
res,
|
|
272
|
+
status: error.status
|
|
273
|
+
})
|
|
377
274
|
next()
|
|
378
275
|
}
|
|
379
276
|
)
|
|
@@ -381,14 +278,14 @@ const applyRoutes = (app: Application): void => {
|
|
|
381
278
|
|
|
382
279
|
export { applyRoutes }
|
|
383
280
|
`,
|
|
384
|
-
file: `${projectName}/src/network/
|
|
281
|
+
file: `${projectName}/src/network/router.ts`
|
|
385
282
|
},
|
|
386
283
|
server: {
|
|
387
284
|
content: `import express from 'express'
|
|
388
285
|
import mongoose from 'mongoose'
|
|
389
286
|
import morgan from 'morgan'
|
|
390
287
|
|
|
391
|
-
import { applyRoutes } from './
|
|
288
|
+
import { applyRoutes } from './router'
|
|
392
289
|
|
|
393
290
|
const PORT = (process.env.PORT as string) || '1996'
|
|
394
291
|
|
|
@@ -421,6 +318,7 @@ class Server {
|
|
|
421
318
|
next()
|
|
422
319
|
}
|
|
423
320
|
)
|
|
321
|
+
|
|
424
322
|
applyRoutes(this._app)
|
|
425
323
|
}
|
|
426
324
|
|
|
@@ -476,46 +374,43 @@ const server = new Server()
|
|
|
476
374
|
export { server as Server }
|
|
477
375
|
`,
|
|
478
376
|
file: `${projectName}/src/network/server.ts`
|
|
479
|
-
},
|
|
480
|
-
index: {
|
|
481
|
-
content: `import { applyRoutes } from './routes'
|
|
482
|
-
import { Server } from './server'
|
|
483
|
-
|
|
484
|
-
export { applyRoutes, Server }
|
|
485
|
-
`,
|
|
486
|
-
file: `${projectName}/src/network/index.ts`
|
|
487
377
|
}
|
|
488
378
|
},
|
|
489
|
-
routes: {
|
|
379
|
+
'network/routes': {
|
|
490
380
|
home: {
|
|
491
381
|
content: `import { Response, Request, Router } from 'express'
|
|
492
382
|
|
|
383
|
+
import { response } from 'network/response'
|
|
384
|
+
|
|
493
385
|
const Home = Router()
|
|
494
386
|
|
|
495
387
|
Home.route('').get((req: Request, res: Response) => {
|
|
496
|
-
response(
|
|
388
|
+
response({
|
|
389
|
+
error: false,
|
|
390
|
+
message: 'Welcome to your Express Backend!',
|
|
391
|
+
res,
|
|
392
|
+
status: 200
|
|
393
|
+
})
|
|
497
394
|
})
|
|
498
395
|
|
|
499
396
|
export { Home }
|
|
500
397
|
`,
|
|
501
|
-
file: `${projectName}/src/routes/home.ts`
|
|
398
|
+
file: `${projectName}/src/network/routes/home.ts`
|
|
502
399
|
},
|
|
503
400
|
index: {
|
|
504
|
-
content: `
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
export { Home, User }
|
|
401
|
+
content: `export * from './home'
|
|
402
|
+
export * from './user'
|
|
508
403
|
`,
|
|
509
|
-
file: `${projectName}/src/routes/index.ts`
|
|
404
|
+
file: `${projectName}/src/network/routes/index.ts`
|
|
510
405
|
},
|
|
511
406
|
user: {
|
|
512
407
|
content: `import { Router, NextFunction } from 'express'
|
|
513
408
|
import httpErrors from 'http-errors'
|
|
514
409
|
import { ValidationError } from 'joi'
|
|
515
410
|
|
|
516
|
-
import {
|
|
517
|
-
import {
|
|
518
|
-
import { idSchema, userSchema } from 'schemas'
|
|
411
|
+
import { response } from 'network/response'
|
|
412
|
+
import { UserService } from 'services/user'
|
|
413
|
+
import { idSchema, userSchema } from './schemas'
|
|
519
414
|
|
|
520
415
|
const User = Router()
|
|
521
416
|
|
|
@@ -529,11 +424,11 @@ User.route('/users')
|
|
|
529
424
|
const {
|
|
530
425
|
body: { args }
|
|
531
426
|
} = req
|
|
532
|
-
const
|
|
427
|
+
const us = new UserService(args as DtoUser)
|
|
533
428
|
|
|
534
429
|
try {
|
|
535
|
-
const result = await
|
|
536
|
-
response(false, result, res, 201)
|
|
430
|
+
const result = await us.process({ type: 'store' })
|
|
431
|
+
response({ error: false, message: result, res, status: 201 })
|
|
537
432
|
} catch (e) {
|
|
538
433
|
next(e)
|
|
539
434
|
}
|
|
@@ -545,11 +440,11 @@ User.route('/users')
|
|
|
545
440
|
res: CustomResponse,
|
|
546
441
|
next: NextFunction
|
|
547
442
|
): Promise<void> => {
|
|
548
|
-
const
|
|
443
|
+
const us = new UserService()
|
|
549
444
|
|
|
550
445
|
try {
|
|
551
|
-
const result = await
|
|
552
|
-
response(false, result, res, 200)
|
|
446
|
+
const result = await us.process({ type: 'getAll' })
|
|
447
|
+
response({ error: false, message: result, res, status: 200 })
|
|
553
448
|
} catch (e) {
|
|
554
449
|
next(e)
|
|
555
450
|
}
|
|
@@ -561,11 +456,11 @@ User.route('/users')
|
|
|
561
456
|
res: CustomResponse,
|
|
562
457
|
next: NextFunction
|
|
563
458
|
): Promise<void> => {
|
|
564
|
-
const
|
|
459
|
+
const us = new UserService()
|
|
565
460
|
|
|
566
461
|
try {
|
|
567
|
-
const result = await
|
|
568
|
-
response(false, result, res, 200)
|
|
462
|
+
const result = await us.process({ type: 'deleteAll' })
|
|
463
|
+
response({ error: false, message: result, res, status: 200 })
|
|
569
464
|
} catch (e) {
|
|
570
465
|
next(e)
|
|
571
466
|
}
|
|
@@ -585,9 +480,9 @@ User.route('/user/:id')
|
|
|
585
480
|
|
|
586
481
|
try {
|
|
587
482
|
await idSchema.validateAsync(id)
|
|
588
|
-
const
|
|
589
|
-
const result = await
|
|
590
|
-
response(false, result, res, 200)
|
|
483
|
+
const us = new UserService({ id } as DtoUser)
|
|
484
|
+
const result = await us.process({ type: 'getOne' })
|
|
485
|
+
response({ error: false, message: result, res, status: 200 })
|
|
591
486
|
} catch (e) {
|
|
592
487
|
if (e instanceof ValidationError)
|
|
593
488
|
return next(new httpErrors.UnprocessableEntity(e.message))
|
|
@@ -613,9 +508,9 @@ User.route('/user/:id')
|
|
|
613
508
|
|
|
614
509
|
try {
|
|
615
510
|
await userSchema.validateAsync(user)
|
|
616
|
-
const
|
|
617
|
-
const result = await
|
|
618
|
-
response(false, result, res, 200)
|
|
511
|
+
const us = new UserService(user)
|
|
512
|
+
const result = await us.process({ type: 'update' })
|
|
513
|
+
response({ error: false, message: result, res, status: 200 })
|
|
619
514
|
} catch (e) {
|
|
620
515
|
if (e instanceof ValidationError)
|
|
621
516
|
return next(new httpErrors.UnprocessableEntity(e.message))
|
|
@@ -636,9 +531,9 @@ User.route('/user/:id')
|
|
|
636
531
|
|
|
637
532
|
try {
|
|
638
533
|
await idSchema.validateAsync(id)
|
|
639
|
-
const
|
|
640
|
-
const result = await
|
|
641
|
-
response(false, result, res, 200)
|
|
534
|
+
const us = new UserService({ id } as DtoUser)
|
|
535
|
+
const result = await us.process({ type: 'delete' })
|
|
536
|
+
response({ error: false, message: result, res, status: 200 })
|
|
642
537
|
} catch (e) {
|
|
643
538
|
if (e instanceof ValidationError)
|
|
644
539
|
return next(new httpErrors.UnprocessableEntity(e.message))
|
|
@@ -650,20 +545,19 @@ User.route('/user/:id')
|
|
|
650
545
|
|
|
651
546
|
export { User }
|
|
652
547
|
`,
|
|
653
|
-
file: `${projectName}/src/routes/user.ts`
|
|
548
|
+
file: `${projectName}/src/network/routes/user.ts`
|
|
654
549
|
}
|
|
655
550
|
},
|
|
656
|
-
schemas: {
|
|
551
|
+
'network/routes/schemas': {
|
|
657
552
|
index: {
|
|
658
553
|
content: `import Joi from 'joi'
|
|
659
554
|
|
|
660
|
-
import { userSchema } from './user'
|
|
661
|
-
|
|
662
555
|
const idSchema = Joi.string().length(24).required()
|
|
663
556
|
|
|
664
|
-
export { idSchema
|
|
557
|
+
export { idSchema }
|
|
558
|
+
export * from './user'
|
|
665
559
|
`,
|
|
666
|
-
file: `${projectName}/src/schemas/index.ts`
|
|
560
|
+
file: `${projectName}/src/network/routes/schemas/index.ts`
|
|
667
561
|
},
|
|
668
562
|
user: {
|
|
669
563
|
content: `import Joi from 'joi'
|
|
@@ -676,7 +570,175 @@ const userSchema = Joi.object().keys({
|
|
|
676
570
|
|
|
677
571
|
export { userSchema }
|
|
678
572
|
`,
|
|
679
|
-
file: `${projectName}/src/schemas/user.ts`
|
|
573
|
+
file: `${projectName}/src/network/routes/schemas/user.ts`
|
|
574
|
+
}
|
|
575
|
+
},
|
|
576
|
+
services: {
|
|
577
|
+
index: {
|
|
578
|
+
content: "export * from './user'\n",
|
|
579
|
+
file: `${projectName}/src/services/index.ts`
|
|
580
|
+
},
|
|
581
|
+
user: {
|
|
582
|
+
content: `import httpErrors from 'http-errors'
|
|
583
|
+
|
|
584
|
+
import { store, remove, get, update } from 'database'
|
|
585
|
+
import { EFU, MFU, GE, errorHandling } from './utils'
|
|
586
|
+
|
|
587
|
+
type Process = {
|
|
588
|
+
type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
class UserService {
|
|
592
|
+
private _args: DtoUser | null
|
|
593
|
+
|
|
594
|
+
constructor(args: DtoUser | null = null) {
|
|
595
|
+
this._args = args
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
public process({ type }: Process): Promise<string | IUser[] | IUser> {
|
|
599
|
+
switch (type) {
|
|
600
|
+
case 'store':
|
|
601
|
+
return this._store()
|
|
602
|
+
case 'getAll':
|
|
603
|
+
return this._getAll()
|
|
604
|
+
case 'deleteAll':
|
|
605
|
+
return this._deleteAll()
|
|
606
|
+
case 'getOne':
|
|
607
|
+
return this._getOne()
|
|
608
|
+
case 'update':
|
|
609
|
+
return this._update()
|
|
610
|
+
case 'delete':
|
|
611
|
+
return this._delete()
|
|
612
|
+
default:
|
|
613
|
+
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
private async _store(): Promise<IUser> {
|
|
618
|
+
try {
|
|
619
|
+
const result = await store(this._args as DtoUser)
|
|
620
|
+
|
|
621
|
+
return result
|
|
622
|
+
} catch (e) {
|
|
623
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
private async _getAll(): Promise<IUser[]> {
|
|
628
|
+
try {
|
|
629
|
+
const users = (await get()) as IUser[]
|
|
630
|
+
|
|
631
|
+
return users
|
|
632
|
+
} catch (e) {
|
|
633
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
private async _deleteAll(): Promise<string> {
|
|
638
|
+
try {
|
|
639
|
+
const usersDeleted = (await remove()) as number
|
|
640
|
+
|
|
641
|
+
if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
|
|
642
|
+
|
|
643
|
+
if (usersDeleted === 0)
|
|
644
|
+
throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
|
|
645
|
+
|
|
646
|
+
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
647
|
+
} catch (e) {
|
|
648
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
private async _getOne(): Promise<IUser> {
|
|
653
|
+
const { id } = this._args as DtoUser
|
|
654
|
+
|
|
655
|
+
try {
|
|
656
|
+
const user = (await get(id as string)) as IUser | null
|
|
657
|
+
|
|
658
|
+
if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
659
|
+
|
|
660
|
+
return user
|
|
661
|
+
} catch (e) {
|
|
662
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
private async _update(): Promise<IUser> {
|
|
667
|
+
try {
|
|
668
|
+
const updatedUser = await update(this._args as DtoUser)
|
|
669
|
+
|
|
670
|
+
if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
671
|
+
|
|
672
|
+
return updatedUser
|
|
673
|
+
} catch (e) {
|
|
674
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
private async _delete(): Promise<string> {
|
|
679
|
+
const { id } = this._args as DtoUser
|
|
680
|
+
|
|
681
|
+
try {
|
|
682
|
+
const deletedUser = await remove(id)
|
|
683
|
+
|
|
684
|
+
if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
685
|
+
|
|
686
|
+
return MFU.USER_DELETED
|
|
687
|
+
} catch (e) {
|
|
688
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
export { UserService }
|
|
694
|
+
`,
|
|
695
|
+
file: `${projectName}/src/services/user.ts`
|
|
696
|
+
}
|
|
697
|
+
},
|
|
698
|
+
'services/utils': {
|
|
699
|
+
index: {
|
|
700
|
+
content: `import httpErrors from 'http-errors'
|
|
701
|
+
|
|
702
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
703
|
+
const errorHandling = (e: any, message?: string): never => {
|
|
704
|
+
console.error(e)
|
|
705
|
+
|
|
706
|
+
if (e instanceof httpErrors.HttpError) throw e
|
|
707
|
+
|
|
708
|
+
throw new httpErrors.InternalServerError(message ?? e.message)
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
export { errorHandling }
|
|
712
|
+
export * from './messages'
|
|
713
|
+
`,
|
|
714
|
+
file: `${projectName}/src/services/utils/index.ts`
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
'services/utils/messages': {
|
|
718
|
+
index: {
|
|
719
|
+
content: `enum GenericErrors {
|
|
720
|
+
INTERNAL_SERVER_ERROR = 'Something went wrong'
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
export { GenericErrors as GE }
|
|
724
|
+
export * from './user'
|
|
725
|
+
`,
|
|
726
|
+
file: `${projectName}/src/services/utils/messages/index.ts`
|
|
727
|
+
},
|
|
728
|
+
user: {
|
|
729
|
+
content: `enum ErrorForUser {
|
|
730
|
+
NOT_FOUND = 'The requested user does not exists',
|
|
731
|
+
NOTHING_TO_DELETE = 'There is no user to be deleted'
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
enum MessageForUser {
|
|
735
|
+
ALL_USERS_DELETED = 'All the users were deleted successfully',
|
|
736
|
+
USER_DELETED = 'The requested user was successfully deleted'
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
export { ErrorForUser as EFU, MessageForUser as MFU }
|
|
740
|
+
`,
|
|
741
|
+
file: `${projectName}/src/services/utils/messages/user.ts`
|
|
680
742
|
}
|
|
681
743
|
},
|
|
682
744
|
test: {
|
|
@@ -1140,10 +1202,7 @@ DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
|
1140
1202
|
file: `${projectName}/src/utils/docs.json`
|
|
1141
1203
|
},
|
|
1142
1204
|
index: {
|
|
1143
|
-
content:
|
|
1144
|
-
|
|
1145
|
-
export { docs }
|
|
1146
|
-
`,
|
|
1205
|
+
content: "export { default as docs } from './docs.json'\n",
|
|
1147
1206
|
file: `${projectName}/src/utils/index.ts`
|
|
1148
1207
|
}
|
|
1149
1208
|
},
|
|
@@ -1162,14 +1221,19 @@ Server.start()
|
|
|
1162
1221
|
|
|
1163
1222
|
await exec(`mkdir ${projectName}/src \
|
|
1164
1223
|
${projectName}/src/@types \
|
|
1165
|
-
${projectName}/src/
|
|
1166
|
-
${projectName}/src/
|
|
1167
|
-
${projectName}/src/
|
|
1168
|
-
${projectName}/src/
|
|
1169
|
-
${projectName}/src/
|
|
1224
|
+
${projectName}/src/@types/dto \
|
|
1225
|
+
${projectName}/src/@types/custom \
|
|
1226
|
+
${projectName}/src/@types/models \
|
|
1227
|
+
${projectName}/src/services \
|
|
1228
|
+
${projectName}/src/services/utils \
|
|
1229
|
+
${projectName}/src/services/utils/messages \
|
|
1230
|
+
${projectName}/src/database \
|
|
1231
|
+
${projectName}/src/database/mongo \
|
|
1232
|
+
${projectName}/src/database/mongo/models \
|
|
1233
|
+
${projectName}/src/database/mongo/queries \
|
|
1170
1234
|
${projectName}/src/network \
|
|
1171
|
-
${projectName}/src/routes \
|
|
1172
|
-
${projectName}/src/schemas \
|
|
1235
|
+
${projectName}/src/network/routes \
|
|
1236
|
+
${projectName}/src/network/routes/schemas \
|
|
1173
1237
|
${projectName}/src/test \
|
|
1174
1238
|
${projectName}/src/utils
|
|
1175
1239
|
`)
|
|
@@ -1177,53 +1241,97 @@ ${projectName}/src/utils
|
|
|
1177
1241
|
// /@types
|
|
1178
1242
|
await writeFile(data['@types'].index.file, data['@types'].index.content)
|
|
1179
1243
|
|
|
1180
|
-
// /
|
|
1181
|
-
await writeFile(
|
|
1182
|
-
|
|
1244
|
+
// /@types/custom
|
|
1245
|
+
await writeFile(
|
|
1246
|
+
data['@types/custom'].request.file,
|
|
1247
|
+
data['@types/custom'].request.content
|
|
1248
|
+
)
|
|
1249
|
+
await writeFile(
|
|
1250
|
+
data['@types/custom'].response.file,
|
|
1251
|
+
data['@types/custom'].response.content
|
|
1252
|
+
)
|
|
1183
1253
|
|
|
1184
|
-
// /
|
|
1254
|
+
// /@types/dto
|
|
1255
|
+
await writeFile(data['@types/dto'].user.file, data['@types/dto'].user.content)
|
|
1256
|
+
|
|
1257
|
+
// /@types/models
|
|
1185
1258
|
await writeFile(
|
|
1186
|
-
data['
|
|
1187
|
-
data['
|
|
1259
|
+
data['@types/models'].user.file,
|
|
1260
|
+
data['@types/models'].user.content
|
|
1188
1261
|
)
|
|
1189
1262
|
|
|
1190
|
-
// /
|
|
1263
|
+
// /services
|
|
1264
|
+
await writeFile(data.services.user.file, data.services.user.content)
|
|
1265
|
+
await writeFile(data.services.index.file, data.services.index.content)
|
|
1266
|
+
|
|
1267
|
+
// /database
|
|
1268
|
+
await writeFile(data.database.index.file, data.database.index.content)
|
|
1191
1269
|
await writeFile(
|
|
1192
|
-
data['
|
|
1193
|
-
data['
|
|
1270
|
+
data['database/mongo'].index.file,
|
|
1271
|
+
data['database/mongo'].index.content
|
|
1194
1272
|
)
|
|
1195
1273
|
await writeFile(
|
|
1196
|
-
data['
|
|
1197
|
-
data['
|
|
1274
|
+
data['database/mongo/models'].index.file,
|
|
1275
|
+
data['database/mongo/models'].index.content
|
|
1276
|
+
)
|
|
1277
|
+
await writeFile(
|
|
1278
|
+
data['database/mongo/models'].user.file,
|
|
1279
|
+
data['database/mongo/models'].user.content
|
|
1280
|
+
)
|
|
1281
|
+
await writeFile(
|
|
1282
|
+
data['database/mongo/queries'].index.file,
|
|
1283
|
+
data['database/mongo/queries'].index.content
|
|
1198
1284
|
)
|
|
1199
|
-
|
|
1200
|
-
// /dto-interfaces
|
|
1201
1285
|
await writeFile(
|
|
1202
|
-
data['
|
|
1203
|
-
data['
|
|
1286
|
+
data['database/mongo/queries'].user.file,
|
|
1287
|
+
data['database/mongo/queries'].user.content
|
|
1204
1288
|
)
|
|
1289
|
+
|
|
1290
|
+
// /services/utils
|
|
1205
1291
|
await writeFile(
|
|
1206
|
-
data['
|
|
1207
|
-
data['
|
|
1292
|
+
data['services/utils'].index.file,
|
|
1293
|
+
data['services/utils'].index.content
|
|
1208
1294
|
)
|
|
1209
1295
|
|
|
1210
|
-
// /
|
|
1211
|
-
await writeFile(
|
|
1212
|
-
|
|
1296
|
+
// /services/utils/messages
|
|
1297
|
+
await writeFile(
|
|
1298
|
+
data['services/utils/messages'].user.file,
|
|
1299
|
+
data['services/utils/messages'].user.content
|
|
1300
|
+
)
|
|
1301
|
+
await writeFile(
|
|
1302
|
+
data['services/utils/messages'].index.file,
|
|
1303
|
+
data['services/utils/messages'].index.content
|
|
1304
|
+
)
|
|
1213
1305
|
|
|
1214
1306
|
// /network
|
|
1215
|
-
await writeFile(data.network.routes.file, data.network.routes.content)
|
|
1216
|
-
await writeFile(data.network.server.file, data.network.server.content)
|
|
1217
1307
|
await writeFile(data.network.index.file, data.network.index.content)
|
|
1308
|
+
await writeFile(data.network.response.file, data.network.response.content)
|
|
1309
|
+
await writeFile(data.network.router.file, data.network.router.content)
|
|
1310
|
+
await writeFile(data.network.server.file, data.network.server.content)
|
|
1218
1311
|
|
|
1219
|
-
// /routes
|
|
1220
|
-
await writeFile(
|
|
1221
|
-
|
|
1222
|
-
|
|
1312
|
+
// /network/routes
|
|
1313
|
+
await writeFile(
|
|
1314
|
+
data['network/routes'].home.file,
|
|
1315
|
+
data['network/routes'].home.content
|
|
1316
|
+
)
|
|
1317
|
+
await writeFile(
|
|
1318
|
+
data['network/routes'].user.file,
|
|
1319
|
+
data['network/routes'].user.content
|
|
1320
|
+
)
|
|
1321
|
+
await writeFile(
|
|
1322
|
+
data['network/routes'].index.file,
|
|
1323
|
+
data['network/routes'].index.content
|
|
1324
|
+
)
|
|
1223
1325
|
|
|
1224
|
-
// /schemas
|
|
1225
|
-
await writeFile(
|
|
1226
|
-
|
|
1326
|
+
// /network/routes/schemas
|
|
1327
|
+
await writeFile(
|
|
1328
|
+
data['network/routes/schemas'].index.file,
|
|
1329
|
+
data['network/routes/schemas'].index.content
|
|
1330
|
+
)
|
|
1331
|
+
await writeFile(
|
|
1332
|
+
data['network/routes/schemas'].user.file,
|
|
1333
|
+
data['network/routes/schemas'].user.content
|
|
1334
|
+
)
|
|
1227
1335
|
|
|
1228
1336
|
// /test
|
|
1229
1337
|
await writeFile(data.test.index.file, data.test.index.content)
|