@anthonylzq/simba.js 2.0.3 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -138,8 +138,6 @@ Regardless of the option chosen, a new folder will be generated with the name of
|
|
|
138
138
|
┃ ┃ ┗ 📜index.ts
|
|
139
139
|
┃ ┣ 📜index.ts
|
|
140
140
|
┃ ┗ 📜user.ts
|
|
141
|
-
┣ 📂test
|
|
142
|
-
┃ ┗ 📜test.http
|
|
143
141
|
┣ 📂utils
|
|
144
142
|
┃ ┣ 📜docs.json
|
|
145
143
|
┃ ┗ 📜index.ts
|
|
@@ -155,6 +153,7 @@ Regardless of the option chosen, a new folder will be generated with the name of
|
|
|
155
153
|
📜nodemon.json
|
|
156
154
|
📜package.json
|
|
157
155
|
📜README.md
|
|
156
|
+
📜index.http
|
|
158
157
|
📜tsconfig.base.json
|
|
159
158
|
📜tsconfig.json
|
|
160
159
|
📜webpack.config.js
|
|
@@ -41,13 +41,12 @@ const writeFile = require('../utils/writeFile')
|
|
|
41
41
|
* | | |- index: content, file
|
|
42
42
|
* | |- user: content, file
|
|
43
43
|
* | |- index: content, file
|
|
44
|
-
* |- test:
|
|
45
|
-
* | |- index.http: content, file
|
|
46
44
|
* |- utils:
|
|
47
45
|
* | |- docs.json: content, file
|
|
48
46
|
* | |- index: content, file
|
|
49
47
|
* |- .env: content, file
|
|
50
48
|
* |- index: content, file
|
|
49
|
+
* index.http: content, file
|
|
51
50
|
*/
|
|
52
51
|
|
|
53
52
|
/**
|
|
@@ -70,45 +69,18 @@ export {}
|
|
|
70
69
|
'@types/dto': {
|
|
71
70
|
user: {
|
|
72
71
|
content: `interface DtoUser {
|
|
73
|
-
id
|
|
74
|
-
lastName
|
|
75
|
-
name
|
|
72
|
+
id: string
|
|
73
|
+
lastName: string
|
|
74
|
+
name: string
|
|
76
75
|
}
|
|
77
76
|
`,
|
|
78
77
|
file: `${projectName}/src/@types/dto/user.d.ts`
|
|
79
78
|
}
|
|
80
79
|
},
|
|
81
|
-
'@types/custom': {
|
|
82
|
-
request: {
|
|
83
|
-
content: `type ExpressRequest = import('express').Request
|
|
84
|
-
|
|
85
|
-
interface CustomRequest extends ExpressRequest {
|
|
86
|
-
body: {
|
|
87
|
-
args?: DtoUser
|
|
88
|
-
}
|
|
89
|
-
// We can add custom headers via intersection, remember that for some reason
|
|
90
|
-
// headers must be in Snake-Pascal-Case
|
|
91
|
-
headers: import('http').IncomingHttpHeaders & {
|
|
92
|
-
'Custom-Header'?: string
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
`,
|
|
96
|
-
file: `${projectName}/src/@types/custom/request.d.ts`
|
|
97
|
-
},
|
|
98
|
-
response: {
|
|
99
|
-
content: `type ExpressResponse = import('express').Response
|
|
100
|
-
|
|
101
|
-
interface CustomResponse extends ExpressResponse {
|
|
102
|
-
newValue?: string
|
|
103
|
-
}
|
|
104
|
-
`,
|
|
105
|
-
file: `${projectName}/src/@types/custom/response.d.ts`
|
|
106
|
-
}
|
|
107
|
-
},
|
|
108
80
|
'@types/models': {
|
|
109
81
|
user: {
|
|
110
82
|
content: `interface IUser {
|
|
111
|
-
|
|
83
|
+
id: string
|
|
112
84
|
name: string
|
|
113
85
|
lastName: string
|
|
114
86
|
updatedAt: Date
|
|
@@ -155,14 +127,14 @@ const User = new Schema<IUser>(
|
|
|
155
127
|
createdAt: false,
|
|
156
128
|
updatedAt: true
|
|
157
129
|
},
|
|
130
|
+
versionKey: false,
|
|
158
131
|
toJSON: {
|
|
159
132
|
transform(_, ret) {
|
|
160
|
-
ret.id = ret._id
|
|
133
|
+
ret.id = ret._id.toString()
|
|
134
|
+
ret.updatedAt = ret.updatedAt.toISOString()
|
|
161
135
|
delete ret._id
|
|
162
136
|
delete ret.__v
|
|
163
|
-
delete ret.updatedAt
|
|
164
137
|
},
|
|
165
|
-
versionKey: false,
|
|
166
138
|
virtuals: true
|
|
167
139
|
}
|
|
168
140
|
}
|
|
@@ -181,12 +153,13 @@ export { UserModel }
|
|
|
181
153
|
file: `${projectName}/src/database/mongo/queries/index.ts`
|
|
182
154
|
},
|
|
183
155
|
user: {
|
|
184
|
-
content: `import { UserModel } from '
|
|
156
|
+
content: `import { UserModel } from '..'
|
|
185
157
|
|
|
186
158
|
const store = async (userData: DtoUser): Promise<IUser> => {
|
|
187
159
|
const user = new UserModel(userData)
|
|
160
|
+
await user.save()
|
|
188
161
|
|
|
189
|
-
return
|
|
162
|
+
return user.toJSON()
|
|
190
163
|
}
|
|
191
164
|
|
|
192
165
|
const remove = async (
|
|
@@ -200,15 +173,22 @@ const remove = async (
|
|
|
200
173
|
const get = async (
|
|
201
174
|
id: string | null = null
|
|
202
175
|
): Promise<IUser[] | IUser | null> => {
|
|
203
|
-
if (id)
|
|
176
|
+
if (id) {
|
|
177
|
+
const user = await UserModel.findById(id)
|
|
178
|
+
|
|
179
|
+
return user ? user.toJSON() : null
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const users = await UserModel.find({})
|
|
204
183
|
|
|
205
|
-
return
|
|
184
|
+
return users.map(u => u.toJSON())
|
|
206
185
|
}
|
|
207
186
|
|
|
208
187
|
const update = async (userData: DtoUser): Promise<IUser | null> => {
|
|
209
188
|
const { id, ...rest } = userData
|
|
189
|
+
const user = await UserModel.findByIdAndUpdate(id, rest, { new: true })
|
|
210
190
|
|
|
211
|
-
return
|
|
191
|
+
return user ? user.toJSON() : null
|
|
212
192
|
}
|
|
213
193
|
|
|
214
194
|
export { store, remove, get, update }
|
|
@@ -222,7 +202,234 @@ export { store, remove, get, update }
|
|
|
222
202
|
export * from './server'
|
|
223
203
|
`,
|
|
224
204
|
file: `${projectName}/src/network/index.ts`
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
services: {
|
|
208
|
+
index: {
|
|
209
|
+
content: "export * from './user'\n",
|
|
210
|
+
file: `${projectName}/src/services/index.ts`
|
|
211
|
+
},
|
|
212
|
+
user: {
|
|
213
|
+
content: `import httpErrors from 'http-errors'
|
|
214
|
+
|
|
215
|
+
import { store, remove, get, update } from 'database'
|
|
216
|
+
import { EFU, MFU, GE, errorHandling } from './utils'
|
|
217
|
+
|
|
218
|
+
type Process = {
|
|
219
|
+
type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
class UserService {
|
|
223
|
+
private _args: Partial<DtoUser> | null
|
|
224
|
+
|
|
225
|
+
constructor(args: Partial<DtoUser> | null = null) {
|
|
226
|
+
this._args = args
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
public process({ type }: Process): Promise<string | IUser[] | IUser> {
|
|
230
|
+
switch (type) {
|
|
231
|
+
case 'store':
|
|
232
|
+
return this._store()
|
|
233
|
+
case 'getAll':
|
|
234
|
+
return this._getAll()
|
|
235
|
+
case 'deleteAll':
|
|
236
|
+
return this._deleteAll()
|
|
237
|
+
case 'getOne':
|
|
238
|
+
return this._getOne()
|
|
239
|
+
case 'update':
|
|
240
|
+
return this._update()
|
|
241
|
+
case 'delete':
|
|
242
|
+
return this._delete()
|
|
243
|
+
default:
|
|
244
|
+
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
private async _store(): Promise<IUser> {
|
|
249
|
+
try {
|
|
250
|
+
const result = await store(this._args as DtoUser)
|
|
251
|
+
|
|
252
|
+
return result
|
|
253
|
+
} catch (e) {
|
|
254
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
private async _getAll(): Promise<IUser[]> {
|
|
259
|
+
try {
|
|
260
|
+
const users = (await get()) as IUser[]
|
|
261
|
+
|
|
262
|
+
return users
|
|
263
|
+
} catch (e) {
|
|
264
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
private async _deleteAll(): Promise<string> {
|
|
269
|
+
try {
|
|
270
|
+
const usersDeleted = (await remove()) as number
|
|
271
|
+
|
|
272
|
+
if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
|
|
273
|
+
|
|
274
|
+
if (usersDeleted === 0)
|
|
275
|
+
throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
|
|
276
|
+
|
|
277
|
+
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
278
|
+
} catch (e) {
|
|
279
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private async _getOne(): Promise<IUser> {
|
|
284
|
+
const { id } = this._args as DtoUser
|
|
285
|
+
|
|
286
|
+
try {
|
|
287
|
+
const user = (await get(id as string)) as IUser | null
|
|
288
|
+
|
|
289
|
+
if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
290
|
+
|
|
291
|
+
return user
|
|
292
|
+
} catch (e) {
|
|
293
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
private async _update(): Promise<IUser> {
|
|
298
|
+
try {
|
|
299
|
+
const updatedUser = await update(this._args as DtoUser)
|
|
300
|
+
|
|
301
|
+
if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
302
|
+
|
|
303
|
+
return updatedUser
|
|
304
|
+
} catch (e) {
|
|
305
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private async _delete(): Promise<string> {
|
|
310
|
+
const { id } = this._args as DtoUser
|
|
311
|
+
|
|
312
|
+
try {
|
|
313
|
+
const deletedUser = await remove(id)
|
|
314
|
+
|
|
315
|
+
if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
316
|
+
|
|
317
|
+
return MFU.USER_DELETED
|
|
318
|
+
} catch (e) {
|
|
319
|
+
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export { UserService }
|
|
325
|
+
`,
|
|
326
|
+
file: `${projectName}/src/services/user.ts`
|
|
327
|
+
}
|
|
328
|
+
},
|
|
329
|
+
'services/utils': {
|
|
330
|
+
index: {
|
|
331
|
+
content: `import httpErrors from 'http-errors'
|
|
332
|
+
|
|
333
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
334
|
+
const errorHandling = (e: any, message?: string): never => {
|
|
335
|
+
console.error(e)
|
|
336
|
+
|
|
337
|
+
if (e instanceof httpErrors.HttpError) throw e
|
|
338
|
+
|
|
339
|
+
throw new httpErrors.InternalServerError(message ?? e.message)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
export { errorHandling }
|
|
343
|
+
export * from './messages'
|
|
344
|
+
`,
|
|
345
|
+
file: `${projectName}/src/services/utils/index.ts`
|
|
346
|
+
}
|
|
347
|
+
},
|
|
348
|
+
'services/utils/messages': {
|
|
349
|
+
index: {
|
|
350
|
+
content: `enum GenericErrors {
|
|
351
|
+
INTERNAL_SERVER_ERROR = 'Something went wrong'
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export { GenericErrors as GE }
|
|
355
|
+
export * from './user'
|
|
356
|
+
`,
|
|
357
|
+
file: `${projectName}/src/services/utils/messages/index.ts`
|
|
225
358
|
},
|
|
359
|
+
user: {
|
|
360
|
+
content: `enum ErrorForUser {
|
|
361
|
+
NOT_FOUND = 'The requested user does not exists',
|
|
362
|
+
NOTHING_TO_DELETE = 'There is no user to be deleted'
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
enum MessageForUser {
|
|
366
|
+
ALL_USERS_DELETED = 'All the users were deleted successfully',
|
|
367
|
+
USER_DELETED = 'The requested user was successfully deleted'
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
export { ErrorForUser as EFU, MessageForUser as MFU }
|
|
371
|
+
`,
|
|
372
|
+
file: `${projectName}/src/services/utils/messages/user.ts`
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
test: {
|
|
376
|
+
index: {
|
|
377
|
+
content: `### Testing store a user
|
|
378
|
+
POST http://localhost:1996/api/users
|
|
379
|
+
Content-Type: application/json
|
|
380
|
+
|
|
381
|
+
{
|
|
382
|
+
"args": {
|
|
383
|
+
"lastName": "Lzq",
|
|
384
|
+
"name": "Anthony"
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
### Testing getAll users
|
|
389
|
+
GET http://localhost:1996/api/users
|
|
390
|
+
|
|
391
|
+
### Testing deleteAll users
|
|
392
|
+
DELETE http://localhost:1996/api/users
|
|
393
|
+
|
|
394
|
+
### Testing getOne user
|
|
395
|
+
GET http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
396
|
+
|
|
397
|
+
### Testing update user
|
|
398
|
+
PATCH http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
399
|
+
Content-Type: application/json
|
|
400
|
+
|
|
401
|
+
{
|
|
402
|
+
"args": {
|
|
403
|
+
"name": "Anthony",
|
|
404
|
+
"lastName": "Luzquiños"
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
### Testing delete user
|
|
409
|
+
DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
410
|
+
`,
|
|
411
|
+
file: `${projectName}/index.http`
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
'.env': {
|
|
415
|
+
content: `MONGO_URI = ${
|
|
416
|
+
process.env.LOCAL
|
|
417
|
+
? process.env.MONGO_URI
|
|
418
|
+
: `mongodb://mongo:mongo@mongo:27017/${projectName}`
|
|
419
|
+
}`,
|
|
420
|
+
file: `${projectName}/.env`
|
|
421
|
+
},
|
|
422
|
+
index: {
|
|
423
|
+
content: `import { Server } from './network'
|
|
424
|
+
|
|
425
|
+
Server.start()
|
|
426
|
+
`,
|
|
427
|
+
file: `${projectName}/src/index.ts`
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const expressData = {
|
|
432
|
+
network: {
|
|
226
433
|
response: {
|
|
227
434
|
content: `interface ResponseProps {
|
|
228
435
|
error: boolean
|
|
@@ -377,6 +584,33 @@ export { server as Server }
|
|
|
377
584
|
file: `${projectName}/src/network/server.ts`
|
|
378
585
|
}
|
|
379
586
|
},
|
|
587
|
+
'@types/custom': {
|
|
588
|
+
request: {
|
|
589
|
+
content: `type ExpressRequest = import('express').Request
|
|
590
|
+
|
|
591
|
+
interface CustomRequest extends ExpressRequest {
|
|
592
|
+
body: {
|
|
593
|
+
args?: DtoUser
|
|
594
|
+
}
|
|
595
|
+
// We can add custom headers via intersection, remember that for some reason
|
|
596
|
+
// headers must be in Snake-Pascal-Case
|
|
597
|
+
headers: import('http').IncomingHttpHeaders & {
|
|
598
|
+
'Custom-Header'?: string
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
`,
|
|
602
|
+
file: `${projectName}/src/@types/custom/request.d.ts`
|
|
603
|
+
},
|
|
604
|
+
response: {
|
|
605
|
+
content: `type ExpressResponse = import('express').Response
|
|
606
|
+
|
|
607
|
+
interface CustomResponse extends ExpressResponse {
|
|
608
|
+
newValue?: string
|
|
609
|
+
}
|
|
610
|
+
`,
|
|
611
|
+
file: `${projectName}/src/@types/custom/response.d.ts`
|
|
612
|
+
}
|
|
613
|
+
},
|
|
380
614
|
'network/routes': {
|
|
381
615
|
home: {
|
|
382
616
|
content: `import { Response, Request, Router } from 'express'
|
|
@@ -411,7 +645,7 @@ import { ValidationError } from 'joi'
|
|
|
411
645
|
|
|
412
646
|
import { response } from 'network/response'
|
|
413
647
|
import { UserService } from 'services/user'
|
|
414
|
-
import { idSchema, userSchema } from './schemas'
|
|
648
|
+
import { idSchema, userSchema, storeUserSchema } from './schemas'
|
|
415
649
|
|
|
416
650
|
const User = Router()
|
|
417
651
|
|
|
@@ -425,12 +659,16 @@ User.route('/users')
|
|
|
425
659
|
const {
|
|
426
660
|
body: { args }
|
|
427
661
|
} = req
|
|
428
|
-
const us = new UserService(args as DtoUser)
|
|
429
662
|
|
|
430
663
|
try {
|
|
664
|
+
await storeUserSchema.validateAsync(args)
|
|
665
|
+
const us = new UserService(args)
|
|
431
666
|
const result = await us.process({ type: 'store' })
|
|
432
667
|
response({ error: false, message: result, res, status: 201 })
|
|
433
668
|
} catch (e) {
|
|
669
|
+
if (e instanceof ValidationError)
|
|
670
|
+
return next(new httpErrors.UnprocessableEntity(e.message))
|
|
671
|
+
|
|
434
672
|
next(e)
|
|
435
673
|
}
|
|
436
674
|
}
|
|
@@ -481,7 +719,7 @@ User.route('/user/:id')
|
|
|
481
719
|
|
|
482
720
|
try {
|
|
483
721
|
await idSchema.validateAsync(id)
|
|
484
|
-
const us = new UserService({ id }
|
|
722
|
+
const us = new UserService({ id })
|
|
485
723
|
const result = await us.process({ type: 'getOne' })
|
|
486
724
|
response({ error: false, message: result, res, status: 200 })
|
|
487
725
|
} catch (e) {
|
|
@@ -502,7 +740,7 @@ User.route('/user/:id')
|
|
|
502
740
|
body: { args },
|
|
503
741
|
params: { id }
|
|
504
742
|
} = req
|
|
505
|
-
const user
|
|
743
|
+
const user = {
|
|
506
744
|
id,
|
|
507
745
|
...args
|
|
508
746
|
}
|
|
@@ -532,7 +770,7 @@ User.route('/user/:id')
|
|
|
532
770
|
|
|
533
771
|
try {
|
|
534
772
|
await idSchema.validateAsync(id)
|
|
535
|
-
const us = new UserService({ id }
|
|
773
|
+
const us = new UserService({ id })
|
|
536
774
|
const result = await us.process({ type: 'delete' })
|
|
537
775
|
response({ error: false, message: result, res, status: 200 })
|
|
538
776
|
} catch (e) {
|
|
@@ -569,216 +807,14 @@ const userSchema = Joi.object().keys({
|
|
|
569
807
|
name: Joi.string().required()
|
|
570
808
|
})
|
|
571
809
|
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
},
|
|
577
|
-
services: {
|
|
578
|
-
index: {
|
|
579
|
-
content: "export * from './user'\n",
|
|
580
|
-
file: `${projectName}/src/services/index.ts`
|
|
581
|
-
},
|
|
582
|
-
user: {
|
|
583
|
-
content: `import httpErrors from 'http-errors'
|
|
584
|
-
|
|
585
|
-
import { store, remove, get, update } from 'database'
|
|
586
|
-
import { EFU, MFU, GE, errorHandling } from './utils'
|
|
587
|
-
|
|
588
|
-
type Process = {
|
|
589
|
-
type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
class UserService {
|
|
593
|
-
private _args: DtoUser | null
|
|
594
|
-
|
|
595
|
-
constructor(args: DtoUser | null = null) {
|
|
596
|
-
this._args = args
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
public process({ type }: Process): Promise<string | IUser[] | IUser> {
|
|
600
|
-
switch (type) {
|
|
601
|
-
case 'store':
|
|
602
|
-
return this._store()
|
|
603
|
-
case 'getAll':
|
|
604
|
-
return this._getAll()
|
|
605
|
-
case 'deleteAll':
|
|
606
|
-
return this._deleteAll()
|
|
607
|
-
case 'getOne':
|
|
608
|
-
return this._getOne()
|
|
609
|
-
case 'update':
|
|
610
|
-
return this._update()
|
|
611
|
-
case 'delete':
|
|
612
|
-
return this._delete()
|
|
613
|
-
default:
|
|
614
|
-
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
private async _store(): Promise<IUser> {
|
|
619
|
-
try {
|
|
620
|
-
const result = await store(this._args as DtoUser)
|
|
621
|
-
|
|
622
|
-
return result
|
|
623
|
-
} catch (e) {
|
|
624
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
private async _getAll(): Promise<IUser[]> {
|
|
629
|
-
try {
|
|
630
|
-
const users = (await get()) as IUser[]
|
|
631
|
-
|
|
632
|
-
return users
|
|
633
|
-
} catch (e) {
|
|
634
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
private async _deleteAll(): Promise<string> {
|
|
639
|
-
try {
|
|
640
|
-
const usersDeleted = (await remove()) as number
|
|
641
|
-
|
|
642
|
-
if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
|
|
643
|
-
|
|
644
|
-
if (usersDeleted === 0)
|
|
645
|
-
throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
|
|
646
|
-
|
|
647
|
-
throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
|
|
648
|
-
} catch (e) {
|
|
649
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
650
|
-
}
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
private async _getOne(): Promise<IUser> {
|
|
654
|
-
const { id } = this._args as DtoUser
|
|
655
|
-
|
|
656
|
-
try {
|
|
657
|
-
const user = (await get(id as string)) as IUser | null
|
|
658
|
-
|
|
659
|
-
if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
660
|
-
|
|
661
|
-
return user
|
|
662
|
-
} catch (e) {
|
|
663
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
private async _update(): Promise<IUser> {
|
|
668
|
-
try {
|
|
669
|
-
const updatedUser = await update(this._args as DtoUser)
|
|
670
|
-
|
|
671
|
-
if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
672
|
-
|
|
673
|
-
return updatedUser
|
|
674
|
-
} catch (e) {
|
|
675
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
676
|
-
}
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
private async _delete(): Promise<string> {
|
|
680
|
-
const { id } = this._args as DtoUser
|
|
681
|
-
|
|
682
|
-
try {
|
|
683
|
-
const deletedUser = await remove(id)
|
|
684
|
-
|
|
685
|
-
if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
|
|
686
|
-
|
|
687
|
-
return MFU.USER_DELETED
|
|
688
|
-
} catch (e) {
|
|
689
|
-
return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
}
|
|
693
|
-
|
|
694
|
-
export { UserService }
|
|
695
|
-
`,
|
|
696
|
-
file: `${projectName}/src/services/user.ts`
|
|
697
|
-
}
|
|
698
|
-
},
|
|
699
|
-
'services/utils': {
|
|
700
|
-
index: {
|
|
701
|
-
content: `import httpErrors from 'http-errors'
|
|
702
|
-
|
|
703
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
704
|
-
const errorHandling = (e: any, message?: string): never => {
|
|
705
|
-
console.error(e)
|
|
706
|
-
|
|
707
|
-
if (e instanceof httpErrors.HttpError) throw e
|
|
708
|
-
|
|
709
|
-
throw new httpErrors.InternalServerError(message ?? e.message)
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
export { errorHandling }
|
|
713
|
-
export * from './messages'
|
|
714
|
-
`,
|
|
715
|
-
file: `${projectName}/src/services/utils/index.ts`
|
|
716
|
-
}
|
|
717
|
-
},
|
|
718
|
-
'services/utils/messages': {
|
|
719
|
-
index: {
|
|
720
|
-
content: `enum GenericErrors {
|
|
721
|
-
INTERNAL_SERVER_ERROR = 'Something went wrong'
|
|
722
|
-
}
|
|
723
|
-
|
|
724
|
-
export { GenericErrors as GE }
|
|
725
|
-
export * from './user'
|
|
726
|
-
`,
|
|
727
|
-
file: `${projectName}/src/services/utils/messages/index.ts`
|
|
728
|
-
},
|
|
729
|
-
user: {
|
|
730
|
-
content: `enum ErrorForUser {
|
|
731
|
-
NOT_FOUND = 'The requested user does not exists',
|
|
732
|
-
NOTHING_TO_DELETE = 'There is no user to be deleted'
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
enum MessageForUser {
|
|
736
|
-
ALL_USERS_DELETED = 'All the users were deleted successfully',
|
|
737
|
-
USER_DELETED = 'The requested user was successfully deleted'
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
export { ErrorForUser as EFU, MessageForUser as MFU }
|
|
741
|
-
`,
|
|
742
|
-
file: `${projectName}/src/services/utils/messages/user.ts`
|
|
743
|
-
}
|
|
744
|
-
},
|
|
745
|
-
test: {
|
|
746
|
-
index: {
|
|
747
|
-
content: `### Testing store a user
|
|
748
|
-
POST http://localhost:1996/api/users
|
|
749
|
-
Content-Type: application/json
|
|
750
|
-
|
|
751
|
-
{
|
|
752
|
-
"args": {
|
|
753
|
-
"lastName": "Lzq",
|
|
754
|
-
"name": "Anthony"
|
|
755
|
-
}
|
|
756
|
-
}
|
|
757
|
-
|
|
758
|
-
### Testing getAll users
|
|
759
|
-
GET http://localhost:1996/api/users
|
|
760
|
-
|
|
761
|
-
### Testing deleteAll users
|
|
762
|
-
DELETE http://localhost:1996/api/users
|
|
763
|
-
|
|
764
|
-
### Testing getOne user
|
|
765
|
-
GET http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
766
|
-
|
|
767
|
-
### Testing update user
|
|
768
|
-
PATCH http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
769
|
-
Content-Type: application/json
|
|
770
|
-
|
|
771
|
-
{
|
|
772
|
-
"args": {
|
|
773
|
-
"name": "Anthony",
|
|
774
|
-
"lastName": "Luzquiños"
|
|
775
|
-
}
|
|
776
|
-
}
|
|
810
|
+
const storeUserSchema = Joi.object().keys({
|
|
811
|
+
lastName: Joi.string().required(),
|
|
812
|
+
name: Joi.string().required()
|
|
813
|
+
})
|
|
777
814
|
|
|
778
|
-
|
|
779
|
-
DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
815
|
+
export { userSchema, storeUserSchema }
|
|
780
816
|
`,
|
|
781
|
-
file: `${projectName}/src/
|
|
817
|
+
file: `${projectName}/src/network/routes/schemas/user.ts`
|
|
782
818
|
}
|
|
783
819
|
},
|
|
784
820
|
utils: {
|
|
@@ -1206,28 +1242,16 @@ DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
|
|
|
1206
1242
|
content: "export { default as docs } from './docs.json'\n",
|
|
1207
1243
|
file: `${projectName}/src/utils/index.ts`
|
|
1208
1244
|
}
|
|
1209
|
-
},
|
|
1210
|
-
'.env': {
|
|
1211
|
-
content: `MONGO_URI = mongodb://mongo:mongo@mongo:27017/${projectName}`,
|
|
1212
|
-
file: `${projectName}/.env`
|
|
1213
|
-
},
|
|
1214
|
-
index: {
|
|
1215
|
-
content: `import { Server } from './network'
|
|
1216
|
-
|
|
1217
|
-
Server.start()
|
|
1218
|
-
`,
|
|
1219
|
-
file: `${projectName}/src/index.ts`
|
|
1220
1245
|
}
|
|
1221
1246
|
}
|
|
1222
1247
|
|
|
1248
|
+
const expressFolders = `${projectName}/src/utils`
|
|
1249
|
+
|
|
1223
1250
|
const createFoldersCommands = `mkdir ${projectName}/src \
|
|
1224
1251
|
${projectName}/src/@types \
|
|
1225
1252
|
${projectName}/src/@types/dto \
|
|
1226
1253
|
${projectName}/src/@types/custom \
|
|
1227
1254
|
${projectName}/src/@types/models \
|
|
1228
|
-
${projectName}/src/services \
|
|
1229
|
-
${projectName}/src/services/utils \
|
|
1230
|
-
${projectName}/src/services/utils/messages \
|
|
1231
1255
|
${projectName}/src/database \
|
|
1232
1256
|
${projectName}/src/database/mongo \
|
|
1233
1257
|
${projectName}/src/database/mongo/models \
|
|
@@ -1235,8 +1259,10 @@ ${projectName}/src/database/mongo/queries \
|
|
|
1235
1259
|
${projectName}/src/network \
|
|
1236
1260
|
${projectName}/src/network/routes \
|
|
1237
1261
|
${projectName}/src/network/routes/schemas \
|
|
1238
|
-
${projectName}/src/
|
|
1239
|
-
${projectName}/src/utils
|
|
1262
|
+
${projectName}/src/services \
|
|
1263
|
+
${projectName}/src/services/utils \
|
|
1264
|
+
${projectName}/src/services/utils/messages \
|
|
1265
|
+
${expressFolders}
|
|
1240
1266
|
`
|
|
1241
1267
|
|
|
1242
1268
|
if (os.platform() === 'win32')
|
|
@@ -1248,12 +1274,12 @@ ${projectName}/src/utils
|
|
|
1248
1274
|
|
|
1249
1275
|
// /@types/custom
|
|
1250
1276
|
await writeFile(
|
|
1251
|
-
|
|
1252
|
-
|
|
1277
|
+
expressData['@types/custom'].request.file,
|
|
1278
|
+
expressData['@types/custom'].request.content
|
|
1253
1279
|
)
|
|
1254
1280
|
await writeFile(
|
|
1255
|
-
|
|
1256
|
-
|
|
1281
|
+
expressData['@types/custom'].response.file,
|
|
1282
|
+
expressData['@types/custom'].response.content
|
|
1257
1283
|
)
|
|
1258
1284
|
|
|
1259
1285
|
// /@types/dto
|
|
@@ -1310,40 +1336,49 @@ ${projectName}/src/utils
|
|
|
1310
1336
|
|
|
1311
1337
|
// /network
|
|
1312
1338
|
await writeFile(data.network.index.file, data.network.index.content)
|
|
1313
|
-
await writeFile(
|
|
1314
|
-
|
|
1315
|
-
|
|
1339
|
+
await writeFile(
|
|
1340
|
+
expressData.network.response.file,
|
|
1341
|
+
expressData.network.response.content
|
|
1342
|
+
)
|
|
1343
|
+
await writeFile(
|
|
1344
|
+
expressData.network.router.file,
|
|
1345
|
+
expressData.network.router.content
|
|
1346
|
+
)
|
|
1347
|
+
await writeFile(
|
|
1348
|
+
expressData.network.server.file,
|
|
1349
|
+
expressData.network.server.content
|
|
1350
|
+
)
|
|
1316
1351
|
|
|
1317
1352
|
// /network/routes
|
|
1318
1353
|
await writeFile(
|
|
1319
|
-
|
|
1320
|
-
|
|
1354
|
+
expressData['network/routes'].home.file,
|
|
1355
|
+
expressData['network/routes'].home.content
|
|
1321
1356
|
)
|
|
1322
1357
|
await writeFile(
|
|
1323
|
-
|
|
1324
|
-
|
|
1358
|
+
expressData['network/routes'].user.file,
|
|
1359
|
+
expressData['network/routes'].user.content
|
|
1325
1360
|
)
|
|
1326
1361
|
await writeFile(
|
|
1327
|
-
|
|
1328
|
-
|
|
1362
|
+
expressData['network/routes'].index.file,
|
|
1363
|
+
expressData['network/routes'].index.content
|
|
1329
1364
|
)
|
|
1330
1365
|
|
|
1331
1366
|
// /network/routes/schemas
|
|
1332
1367
|
await writeFile(
|
|
1333
|
-
|
|
1334
|
-
|
|
1368
|
+
expressData['network/routes/schemas'].index.file,
|
|
1369
|
+
expressData['network/routes/schemas'].index.content
|
|
1335
1370
|
)
|
|
1336
1371
|
await writeFile(
|
|
1337
|
-
|
|
1338
|
-
|
|
1372
|
+
expressData['network/routes/schemas'].user.file,
|
|
1373
|
+
expressData['network/routes/schemas'].user.content
|
|
1339
1374
|
)
|
|
1340
1375
|
|
|
1341
1376
|
// /test
|
|
1342
1377
|
await writeFile(data.test.index.file, data.test.index.content)
|
|
1343
1378
|
|
|
1344
1379
|
// /utils
|
|
1345
|
-
await writeFile(
|
|
1346
|
-
await writeFile(
|
|
1380
|
+
await writeFile(expressData.utils.docs.file, expressData.utils.docs.content)
|
|
1381
|
+
await writeFile(expressData.utils.index.file, expressData.utils.index.content)
|
|
1347
1382
|
|
|
1348
1383
|
// .env
|
|
1349
1384
|
await writeFile(data['.env'].file, data['.env'].content)
|
|
@@ -6,71 +6,71 @@ const writeFile = require('../utils/writeFile')
|
|
|
6
6
|
*/
|
|
7
7
|
module.exports = async projectName => {
|
|
8
8
|
const data = {
|
|
9
|
-
eslintContent: `
|
|
10
|
-
env: {
|
|
11
|
-
node: true
|
|
9
|
+
eslintContent: `{
|
|
10
|
+
"env": {
|
|
11
|
+
"node": true
|
|
12
12
|
},
|
|
13
|
-
root: true,
|
|
14
|
-
parser:
|
|
15
|
-
plugins: [
|
|
16
|
-
extends: [
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
"root": true,
|
|
14
|
+
"parser": "@typescript-eslint/parser",
|
|
15
|
+
"plugins": ["@typescript-eslint", "import", "prettier"],
|
|
16
|
+
"extends": [
|
|
17
|
+
"standard",
|
|
18
|
+
"eslint:recommended",
|
|
19
|
+
"plugin:@typescript-eslint/eslint-recommended",
|
|
20
|
+
"plugin:@typescript-eslint/recommended",
|
|
21
|
+
"prettier"
|
|
22
22
|
],
|
|
23
|
-
rules: {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
"rules": {
|
|
24
|
+
"@typescript-eslint/no-var-requires": "off",
|
|
25
|
+
"@typescript-eslint/no-empty-interface": "off",
|
|
26
|
+
"arrow-parens": ["error", "as-needed"],
|
|
27
|
+
"import/extensions": [
|
|
28
28
|
2,
|
|
29
29
|
{
|
|
30
|
-
ts:
|
|
31
|
-
js:
|
|
32
|
-
json:
|
|
30
|
+
"ts": "never",
|
|
31
|
+
"js": "always",
|
|
32
|
+
"json": "always"
|
|
33
33
|
}
|
|
34
34
|
],
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
"import/no-extraneous-dependencies": [
|
|
36
|
+
"error",
|
|
37
37
|
{
|
|
38
|
-
devDependencies: [
|
|
39
|
-
optionalDependencies: [
|
|
40
|
-
peerDependencies: [
|
|
38
|
+
"devDependencies": ["**/*.test.js", "webpack.config.js"],
|
|
39
|
+
"optionalDependencies": ["**/*.test.js"],
|
|
40
|
+
"peerDependencies": ["**/*.test.js"]
|
|
41
41
|
}
|
|
42
42
|
],
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
"max-len": [
|
|
44
|
+
"error",
|
|
45
45
|
{
|
|
46
|
-
code: 80,
|
|
47
|
-
ignoreComments: true,
|
|
48
|
-
ignoreRegExpLiterals: true,
|
|
49
|
-
ignoreTemplateLiterals: true,
|
|
50
|
-
ignoreTrailingComments: true,
|
|
51
|
-
ignoreStrings: true,
|
|
52
|
-
ignoreUrls: true
|
|
46
|
+
"code": 80,
|
|
47
|
+
"ignoreComments": true,
|
|
48
|
+
"ignoreRegExpLiterals": true,
|
|
49
|
+
"ignoreTemplateLiterals": true,
|
|
50
|
+
"ignoreTrailingComments": true,
|
|
51
|
+
"ignoreStrings": true,
|
|
52
|
+
"ignoreUrls": true
|
|
53
53
|
}
|
|
54
54
|
],
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
"newline-before-return": "error",
|
|
56
|
+
"object-curly-spacing": ["error", "always"],
|
|
57
57
|
"object-shorthand": ["error", "always"],
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
"prefer-const": "error",
|
|
59
|
+
"prettier/prettier": [
|
|
60
|
+
"error",
|
|
61
61
|
{
|
|
62
|
-
arrowParens:
|
|
63
|
-
bracketSpacing: true,
|
|
64
|
-
printWidth: 80,
|
|
65
|
-
quoteProps:
|
|
66
|
-
semi: false,
|
|
67
|
-
singleQuote: true,
|
|
68
|
-
tabWidth: 2,
|
|
69
|
-
trailingComma:
|
|
62
|
+
"arrowParens": "avoid",
|
|
63
|
+
"bracketSpacing": true,
|
|
64
|
+
"printWidth": 80,
|
|
65
|
+
"quoteProps": "as-needed",
|
|
66
|
+
"semi": false,
|
|
67
|
+
"singleQuote": true,
|
|
68
|
+
"tabWidth": 2,
|
|
69
|
+
"trailingComma": "none"
|
|
70
70
|
}
|
|
71
71
|
],
|
|
72
|
-
radix: [
|
|
73
|
-
|
|
72
|
+
"radix": ["error", "as-needed"],
|
|
73
|
+
"spaced-comment": ["error", "always"]
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
`,
|
|
@@ -14,7 +14,7 @@ const eslint = require('./functions/eslint')
|
|
|
14
14
|
const webpack = require('./functions/webpack')
|
|
15
15
|
const docker = require('./functions/docker')
|
|
16
16
|
const herokuF = require('./functions/heroku')
|
|
17
|
-
const express = require('./functions/
|
|
17
|
+
const express = require('./functions/api')
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {Number} process number of process
|
|
@@ -56,13 +56,13 @@ module.exports = async ({
|
|
|
56
56
|
cliProgress.Presets.shades_classic
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
-
const
|
|
59
|
+
const expressProdPackages = 'express joi morgan swagger-ui-express'
|
|
60
|
+
const prodPackages = `${manager} http-errors mongoose ${expressProdPackages}`
|
|
61
|
+
|
|
62
|
+
const expressDevPackages = `@types/express @types/morgan @types/swagger-ui-express`
|
|
60
63
|
const devPackages = `${manager} -D \
|
|
61
|
-
@types/express \
|
|
62
64
|
@types/http-errors \
|
|
63
|
-
@types/morgan \
|
|
64
65
|
@types/node \
|
|
65
|
-
@types/swagger-ui-express \
|
|
66
66
|
@typescript-eslint/eslint-plugin \
|
|
67
67
|
@typescript-eslint/parser \
|
|
68
68
|
dotenv \
|
|
@@ -70,7 +70,9 @@ eslint \
|
|
|
70
70
|
eslint-config-prettier \
|
|
71
71
|
eslint-config-standard \
|
|
72
72
|
eslint-plugin-import \
|
|
73
|
+
eslint-plugin-node \
|
|
73
74
|
eslint-plugin-prettier \
|
|
75
|
+
eslint-plugin-promise \
|
|
74
76
|
nodemon \
|
|
75
77
|
prettier \
|
|
76
78
|
standard-version \
|
|
@@ -81,7 +83,8 @@ tsconfig-paths-webpack-plugin \
|
|
|
81
83
|
typescript \
|
|
82
84
|
webpack \
|
|
83
85
|
webpack-cli \
|
|
84
|
-
webpack-node-externals
|
|
86
|
+
webpack-node-externals \
|
|
87
|
+
${expressDevPackages}`
|
|
85
88
|
|
|
86
89
|
bar.start(process, i)
|
|
87
90
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anthonylzq/simba.js",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "set up a modern backend app by running one command",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"directories": {
|
|
@@ -10,9 +10,10 @@
|
|
|
10
10
|
"scripts": {
|
|
11
11
|
"service": "node ./bin",
|
|
12
12
|
"release": "standard-version",
|
|
13
|
-
"test": "npm run rm && node ./bin -N example -D 'This is a test' -a AnthonyLzq -e sluzquinosa@uni.pe -l mit -H",
|
|
13
|
+
"test": "npm run rm && node -r dotenv/config ./bin -N example -D 'This is a test' -a AnthonyLzq -e sluzquinosa@uni.pe -l mit -H && npm run rm-git-example",
|
|
14
14
|
"lint": "eslint --ext js lib/ --fix",
|
|
15
|
-
"rm": "if [ -d \"example\" ]; then rm -rf example; fi"
|
|
15
|
+
"rm": "if [ -d \"example\" ]; then rm -rf example; fi",
|
|
16
|
+
"rm-git-example": "if [ -d \"example/.git\" ]; then rm -rf example/.git; fi"
|
|
16
17
|
},
|
|
17
18
|
"bin": {
|
|
18
19
|
"simba": "./bin/index.js"
|
|
@@ -34,9 +35,10 @@
|
|
|
34
35
|
"colors": "^1.4.0",
|
|
35
36
|
"readline-sync": "^1.4.10",
|
|
36
37
|
"underscore": "^1.13.2",
|
|
37
|
-
"yargs": "^17.3.
|
|
38
|
+
"yargs": "^17.3.1"
|
|
38
39
|
},
|
|
39
40
|
"devDependencies": {
|
|
41
|
+
"dotenv": "^14.3.2",
|
|
40
42
|
"eslint": "^8.5.0",
|
|
41
43
|
"eslint-config-prettier": "^8.3.0",
|
|
42
44
|
"eslint-config-standard": "^16.0.3",
|