@anthonylzq/simba.js 4.2.0 → 4.4.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.
@@ -1,1982 +0,0 @@
1
- const os = require('os')
2
- const util = require('util')
3
- const exec = util.promisify(require('child_process').exec)
4
- const writeFile = require('../utils/writeFile')
5
-
6
- /*
7
- * Express api:
8
- * src
9
- * |- @types:
10
- * |- |- custom:
11
- * |- |- |- request: content, file
12
- * |- |- |- response: content, file
13
- * |- |- dto:
14
- * |- |- |- user: content, file
15
- * |- |- models:
16
- * |- |- |- user: content, file
17
- * | |- index: content, file
18
- * |- database:
19
- * | |- mongo:
20
- * | |- |- models:
21
- * | |- |- |- index: content, file
22
- * | |- |- |- user: content, file
23
- * | |- |- queries:
24
- * | |- |- |- index: content, file
25
- * | |- |- |- user: content, file
26
- * | |- |- index: content, file
27
- * | |- index: content, file
28
- * |- network:
29
- * | |- routes:
30
- * | | |- schemas:
31
- * | | | |- user: content, file
32
- * | | | |- index: content, file
33
- * | | |- home: content, file
34
- * | | |- index: content, file
35
- * | | |- user: content, file
36
- * | |- response: content, file
37
- * | |- router: content, file
38
- * | |- server: content, file
39
- * | |- index: content, file
40
- * |- services:
41
- * | |- utils:
42
- * | | |- messages:
43
- * | | | |- user: content, file
44
- * | | | |- index: content, file
45
- * | | |- index: content, file
46
- * | |- user: content, file
47
- * | |- index: content, file
48
- * |- utils:
49
- * | |- docs.json: content, file
50
- * | |- index: content, file
51
- * |- .env: content, file
52
- * |- index: content, file
53
- * index.http: content, file
54
- */
55
-
56
- /*
57
- * Fastify api:
58
- * src
59
- * |- @types:
60
- * |- |- dto:
61
- * |- |- |- user: content, file
62
- * |- |- models:
63
- * |- |- |- user: content, file
64
- * | |- index: content, file
65
- * |- database:
66
- * | |- mongo:
67
- * | |- |- models:
68
- * | |- |- |- index: content, file
69
- * | |- |- |- user: content, file
70
- * | |- |- queries:
71
- * | |- |- |- index: content, file
72
- * | |- |- |- user: content, file
73
- * | |- |- index: content, file
74
- * | |- index: content, file
75
- * |- network:
76
- * | |- routes:
77
- * | | |- schemas:
78
- * | | | |- user: content, file
79
- * | | | |- index: content, file
80
- * | | |- home: content, file
81
- * | | |- user: content, file
82
- * | | |- index: content, file
83
- * | |- response: content, file
84
- * | |- router: content, file
85
- * | |- server: content, file
86
- * | |- index: content, file
87
- * |- services:
88
- * | |- utils:
89
- * | | |- messages:
90
- * | | | |- user: content, file
91
- * | | | |- index: content, file
92
- * | | |- index: content, file
93
- * | |- user: content, file
94
- * | |- index: content, file
95
- * |- .env: content, file
96
- * |- index: content, file
97
- * index.http: content, file
98
- */
99
-
100
- /**
101
- * @param {Object} args
102
- * @param {String} args.projectName
103
- * @param {String} args.projectVersion
104
- * @param {String} args.email
105
- * @param {Boolean|undefined} args.fastify
106
- */
107
- module.exports = async ({
108
- projectName,
109
- projectVersion,
110
- email,
111
- fastify = false
112
- }) => {
113
- const data = {
114
- '@types': {
115
- index: {
116
- content: `/* eslint-disable no-var */
117
- declare global {}
118
-
119
- export {}
120
- `,
121
- file: `${projectName}/src/@types/index.d.ts`
122
- }
123
- },
124
- '@types/models': {
125
- user: {
126
- content: `interface UserDBO {
127
- id: string
128
- name: string
129
- lastName: string
130
- createdAt: Date
131
- updatedAt: Date
132
- }
133
- `,
134
- file: `${projectName}/src/@types/models/user.d.ts`
135
- }
136
- },
137
- database: {
138
- index: {
139
- content: "export * from './mongo'\n",
140
- file: `${projectName}/src/database/index.ts`
141
- }
142
- },
143
- 'database/mongo': {
144
- index: {
145
- content: `export * from './models'
146
- export * from './queries'
147
- `,
148
- file: `${projectName}/src/database/mongo/index.ts`
149
- }
150
- },
151
- 'database/mongo/models': {
152
- index: {
153
- content: "export * from './user'\n",
154
- file: `${projectName}/src/database/mongo/models/index.ts`
155
- },
156
- user: {
157
- content: `import { model, Schema } from 'mongoose'
158
-
159
- const UserSchema = new Schema<UserDBO>(
160
- {
161
- lastName: {
162
- required: true,
163
- type: String
164
- },
165
- name: {
166
- required: true,
167
- type: String
168
- }
169
- },
170
- {
171
- timestamps: true,
172
- versionKey: false,
173
- toObject: {
174
- transform: (_, ret) => {
175
- ret.id = ret._id.toString()
176
- delete ret._id
177
- }
178
- }
179
- }
180
- )
181
-
182
- const UserModel = model<UserDBO>('users', UserSchema)
183
-
184
- export { UserModel }
185
- `,
186
- file: `${projectName}/src/database/mongo/models/user.ts`
187
- }
188
- },
189
- 'database/mongo/queries': {
190
- index: {
191
- content: "export * from './user'\n",
192
- file: `${projectName}/src/database/mongo/queries/index.ts`
193
- },
194
- user: {
195
- content: `import { Document, Types } from 'mongoose'
196
-
197
- import { UserModel } from '..'
198
- import { UserDTO } from 'schemas'
199
-
200
- const userDBOtoDTO = (
201
- userDBO: Document<unknown, unknown, UserDBO> &
202
- UserDBO & {
203
- _id: Types.ObjectId
204
- }
205
- ): UserDTO => ({
206
- ...userDBO.toObject(),
207
- createdAt: userDBO.createdAt.toISOString(),
208
- updatedAt: userDBO.updatedAt.toISOString()
209
- })
210
-
211
- const store = async (userData: UserDTO): Promise<UserDTO> => {
212
- const user = new UserModel(userData)
213
-
214
- await user.save()
215
-
216
- return userDBOtoDTO(user)
217
- }
218
-
219
- const remove = async (
220
- id: string | null = null
221
- ): Promise<UserDTO | number | null> => {
222
- if (id) {
223
- const removedUser = await UserModel.findByIdAndRemove(id)
224
-
225
- if (!removedUser) return null
226
-
227
- return userDBOtoDTO(removedUser)
228
- }
229
-
230
- return (await UserModel.deleteMany({})).deletedCount
231
- }
232
-
233
- const get = async (
234
- id: string | null = null
235
- ): Promise<UserDTO[] | UserDTO | null> => {
236
- if (id) {
237
- const user = await UserModel.findById(id)
238
-
239
- return user ? userDBOtoDTO(user) : null
240
- }
241
-
242
- const users = await UserModel.find({})
243
-
244
- return users.map(u => userDBOtoDTO(u))
245
- }
246
-
247
- const update = async (userData: UserDTO): Promise<UserDTO | null> => {
248
- const { id, ...rest } = userData
249
- const user = await UserModel.findByIdAndUpdate(id, rest, { new: true })
250
-
251
- return user ? userDBOtoDTO(user) : null
252
- }
253
-
254
- export { store, remove, get, update }
255
- `,
256
- file: `${projectName}/src/database/mongo/queries/user.ts`
257
- }
258
- },
259
- network: {
260
- index: {
261
- content: `export * from './routes'
262
- export * from './server'
263
- `,
264
- file: `${projectName}/src/network/index.ts`
265
- }
266
- },
267
- schemas: {
268
- index: {
269
- content: `import { Static, Type } from '@sinclair/typebox'
270
-
271
- const id = Type.String({
272
- pattern: '^[a-zA-Z0-9]{24,}$'
273
- })
274
-
275
- type Id = Static<typeof id>
276
-
277
- const idSchema = Type.Object({ id })
278
-
279
- type IdSchema = Static<typeof idSchema>
280
-
281
- export { id, Id, idSchema, IdSchema }
282
- export * from './user'
283
- `,
284
- file: `${projectName}/src/schemas/index.ts`
285
- },
286
- user: {
287
- content: `import { Static, Type } from '@sinclair/typebox'
288
-
289
- import { id } from '.'
290
-
291
- const user = Type.Object({
292
- lastName: Type.String(),
293
- name: Type.String()
294
- })
295
-
296
- type User = Static<typeof user>
297
-
298
- const userDto = Type.Object({
299
- id: Type.Optional(id),
300
- lastName: Type.String(),
301
- name: Type.String(),
302
- createdAt: Type.Optional(Type.String()),
303
- updatedAt: Type.Optional(Type.String())
304
- })
305
-
306
- type UserDTO = Static<typeof userDto>
307
-
308
- const storeUserSchema = Type.Object({
309
- args: user
310
- })
311
-
312
- type StoreUser = Static<typeof storeUserSchema>
313
-
314
- export { userDto, UserDTO, user, User, storeUserSchema, StoreUser }
315
- `,
316
- file: `${projectName}/src/schemas/user.ts`
317
- }
318
- },
319
- services: {
320
- index: {
321
- content: "export * from './user'\n",
322
- file: `${projectName}/src/services/index.ts`
323
- },
324
- user: {
325
- content: `import httpErrors from 'http-errors'
326
-
327
- import { store, remove, get, update } from 'database'
328
- import { UserDTO } from 'schemas'
329
- import { EFU, MFU, GE, errorHandling } from './utils'
330
-
331
- type Process = {
332
- type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
333
- }
334
-
335
- type Arguments = {
336
- id?: string
337
- userDto?: UserDTO
338
- userDtoWithoutId?: Omit<UserDTO, 'id'>
339
- }
340
-
341
- class UserService {
342
- #args: Arguments
343
-
344
- constructor(args: Arguments = {}) {
345
- this.#args = args
346
- }
347
-
348
- public process({ type }: Process): Promise<string | UserDTO | UserDTO[]> {
349
- switch (type) {
350
- case 'store':
351
- return this.#store()
352
- case 'getAll':
353
- return this.#getAll()
354
- case 'deleteAll':
355
- return this.#deleteAll()
356
- case 'getOne':
357
- return this.#getOne()
358
- case 'update':
359
- return this.#update()
360
- case 'delete':
361
- return this.#delete()
362
- default:
363
- throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
364
- }
365
- }
366
-
367
- async #store(): Promise<UserDTO> {
368
- try {
369
- if (!this.#args.userDtoWithoutId)
370
- throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
371
-
372
- const result = await store({
373
- ...this.#args.userDtoWithoutId
374
- })
375
-
376
- return result
377
- } catch (e) {
378
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
379
- }
380
- }
381
-
382
- async #getAll(): Promise<UserDTO[]> {
383
- try {
384
- const users = (await get()) as UserDTO[]
385
-
386
- return users
387
- } catch (e) {
388
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
389
- }
390
- }
391
-
392
- async #deleteAll(): Promise<string> {
393
- try {
394
- const usersDeleted = (await remove()) as number
395
-
396
- if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
397
-
398
- if (usersDeleted === 0)
399
- throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
400
-
401
- throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
402
- } catch (e) {
403
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
404
- }
405
- }
406
-
407
- async #getOne(): Promise<UserDTO> {
408
- try {
409
- if (!this.#args.id)
410
- throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
411
-
412
- const { id } = this.#args
413
- const user = (await get(id)) as UserDTO | null
414
-
415
- if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
416
-
417
- return user
418
- } catch (e) {
419
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
420
- }
421
- }
422
-
423
- async #update(): Promise<UserDTO> {
424
- try {
425
- if (!this.#args.userDto || !this.#args.userDto.id)
426
- throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
427
-
428
- const updatedUser = await update(this.#args.userDto)
429
-
430
- if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
431
-
432
- return updatedUser
433
- } catch (e) {
434
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
435
- }
436
- }
437
-
438
- async #delete(): Promise<string> {
439
- try {
440
- if (!this.#args.id)
441
- throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
442
-
443
- const { id } = this.#args
444
- const deletedUser = await remove(id)
445
-
446
- if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
447
-
448
- return MFU.USER_DELETED
449
- } catch (e) {
450
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
451
- }
452
- }
453
- }
454
-
455
- export { UserService }
456
- `,
457
- file: `${projectName}/src/services/user.ts`
458
- }
459
- },
460
- 'services/utils': {
461
- index: {
462
- content: `import httpErrors from 'http-errors'
463
-
464
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
465
- const errorHandling = (e: any, message?: string): never => {
466
- console.error(e)
467
-
468
- if (e instanceof httpErrors.HttpError) throw e
469
-
470
- throw new httpErrors.InternalServerError(message ?? e.message)
471
- }
472
-
473
- export { errorHandling }
474
- export * from './messages'
475
- `,
476
- file: `${projectName}/src/services/utils/index.ts`
477
- }
478
- },
479
- 'services/utils/messages': {
480
- index: {
481
- content: `enum GenericErrors {
482
- INTERNAL_SERVER_ERROR = 'Something went wrong'
483
- }
484
-
485
- export { GenericErrors as GE }
486
- export * from './user'
487
- `,
488
- file: `${projectName}/src/services/utils/messages/index.ts`
489
- },
490
- user: {
491
- content: `enum ErrorForUser {
492
- NOT_FOUND = 'The requested user does not exists',
493
- NOTHING_TO_DELETE = 'There is no user to be deleted'
494
- }
495
-
496
- enum MessageForUser {
497
- ALL_USERS_DELETED = 'All the users were deleted successfully',
498
- USER_DELETED = 'The requested user was successfully deleted'
499
- }
500
-
501
- export { ErrorForUser as EFU, MessageForUser as MFU }
502
- `,
503
- file: `${projectName}/src/services/utils/messages/user.ts`
504
- }
505
- },
506
- test: {
507
- index: {
508
- content: `### Testing store a user
509
- POST http://localhost:1996/api/users
510
- Content-Type: application/json
511
-
512
- {
513
- "args": {
514
- "lastName": "Lzq",
515
- "name": "Anthony"
516
- }
517
- }
518
-
519
- ### Testing getAll users
520
- GET http://localhost:1996/api/users
521
-
522
- ### Testing deleteAll users
523
- DELETE http://localhost:1996/api/users
524
-
525
- ### Testing getOne user
526
- GET http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
527
-
528
- ### Testing update user
529
- PATCH http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
530
- Content-Type: application/json
531
-
532
- {
533
- "args": {
534
- "name": "Anthony",
535
- "lastName": "Luzquiños"
536
- }
537
- }
538
-
539
- ### Testing delete user
540
- DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
541
- `,
542
- file: `${projectName}/index.http`
543
- }
544
- },
545
- '.env': {
546
- content: `MONGO_URI = ${
547
- process.env.LOCAL
548
- ? process.env.MONGO_URI
549
- : `mongodb://mongo:mongo@mongo:27017/${projectName}`
550
- }`,
551
- file: `${projectName}/.env`
552
- },
553
- index: {
554
- content: `import { Server } from './network'
555
-
556
- Server.start()
557
- `,
558
- file: `${projectName}/src/index.ts`
559
- }
560
- }
561
-
562
- const expressData = {
563
- '@types/custom': {
564
- request: {
565
- content: `type ExpressRequest = import('express').Request
566
-
567
- interface CustomRequest extends ExpressRequest {
568
- body: {
569
- args?: import('schemas').UserDTO
570
- }
571
- // We can add custom headers via intersection, remember that for some reason
572
- // headers must be in Snake-Pascal-Case
573
- headers: import('http').IncomingHttpHeaders & {
574
- 'Custom-Header'?: string
575
- }
576
- }
577
- `,
578
- file: `${projectName}/src/@types/custom/request.d.ts`
579
- },
580
- response: {
581
- content: `type ExpressResponse = import('express').Response
582
-
583
- interface CustomResponse extends ExpressResponse {
584
- newValue?: string
585
- }
586
- `,
587
- file: `${projectName}/src/@types/custom/response.d.ts`
588
- }
589
- },
590
- network: {
591
- response: {
592
- content: `interface ResponseProps {
593
- error: boolean
594
- message: unknown
595
- res: CustomResponse
596
- status: number
597
- }
598
-
599
- const response = ({ error, message, res, status }: ResponseProps): void => {
600
- res.status(status).send({ error, message })
601
- }
602
-
603
- export { response }
604
- `,
605
- file: `${projectName}/src/network/response.ts`
606
- },
607
- router: {
608
- content: `import { Application, Response, Request, Router, NextFunction } from 'express'
609
- import swaggerUi from 'swagger-ui-express'
610
- import httpErrors from 'http-errors'
611
-
612
- import { response } from './response'
613
- import { Home, User } from './routes'
614
- import { docs } from 'utils'
615
-
616
- const routers = [User]
617
-
618
- const applyRoutes = (app: Application): void => {
619
- app.use('/', Home)
620
- app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(docs))
621
- routers.forEach((router: Router): Application => app.use('/api', router))
622
-
623
- // Handling 404 error
624
- app.use((req, res, next) => {
625
- next(new httpErrors.NotFound('This route does not exists'))
626
- })
627
- app.use(
628
- (
629
- error: httpErrors.HttpError,
630
- req: Request,
631
- res: Response,
632
- next: NextFunction
633
- ) => {
634
- response({
635
- error: true,
636
- message: error.message,
637
- res,
638
- status: error.status
639
- })
640
- next()
641
- }
642
- )
643
- }
644
-
645
- export { applyRoutes }
646
- `,
647
- file: `${projectName}/src/network/router.ts`
648
- },
649
- server: {
650
- content: `import express from 'express'
651
- import mongoose from 'mongoose'
652
- import morgan from 'morgan'
653
- import cors from 'cors'
654
-
655
- import { applyRoutes } from './router'
656
-
657
- const PORT = (process.env.PORT as string) || '1996'
658
-
659
- class Server {
660
- #app: express.Application
661
- #connection: mongoose.Connection | undefined
662
-
663
- constructor() {
664
- this.#app = express()
665
- this.#config()
666
- }
667
-
668
- #config() {
669
- this.#app.use(cors())
670
- this.#app.use(morgan('dev'))
671
- this.#app.use(express.json())
672
- this.#app.use(express.urlencoded({ extended: false }))
673
- this.#app.use(
674
- (
675
- req: express.Request,
676
- res: express.Response,
677
- next: express.NextFunction
678
- ) => {
679
- res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE')
680
- res.header('Access-Control-Allow-Origin', '*')
681
- res.header(
682
- 'Access-Control-Allow-Headers',
683
- 'Authorization, Content-Type'
684
- )
685
- next()
686
- }
687
- )
688
-
689
- applyRoutes(this.#app)
690
- }
691
-
692
- async #mongo(): Promise<void> {
693
- this.#connection = mongoose.connection
694
- const connection = {
695
- keepAlive: true,
696
- useNewUrlParser: true,
697
- useUnifiedTopology: true
698
- }
699
- this.#connection.on('connected', () => {
700
- console.log('Mongo connection established.')
701
- })
702
- this.#connection.on('reconnected', () => {
703
- console.log('Mongo connection reestablished')
704
- })
705
- this.#connection.on('disconnected', () => {
706
- console.log('Mongo connection disconnected')
707
- console.log('Trying to reconnected to Mongo...')
708
- setTimeout(() => {
709
- mongoose.connect(process.env.MONGO_URI as string, {
710
- ...connection,
711
- connectTimeoutMS: 3000,
712
- socketTimeoutMS: 3000
713
- })
714
- }, 3000)
715
- })
716
- this.#connection.on('close', () => {
717
- console.log('Mongo connection closed')
718
- })
719
- this.#connection.on('error', (e: Error) => {
720
- console.log('Mongo connection error:')
721
- console.error(e)
722
- })
723
- await mongoose.connect(process.env.MONGO_URI as string, connection)
724
- }
725
-
726
- public start(): void {
727
- this.#app.listen(PORT, () => {
728
- console.log(\`Server running at port \${PORT}\`)
729
- })
730
-
731
- try {
732
- this.#mongo()
733
- } catch (e) {
734
- console.error(e)
735
- }
736
- }
737
- }
738
-
739
- const server = new Server()
740
-
741
- export { server as Server }
742
- `,
743
- file: `${projectName}/src/network/server.ts`
744
- }
745
- },
746
- 'network/routes': {
747
- home: {
748
- content: `import { Response, Request, Router } from 'express'
749
-
750
- import { response } from 'network/response'
751
-
752
- const Home = Router()
753
-
754
- Home.route('').get((req: Request, res: Response) => {
755
- response({
756
- error: false,
757
- message: 'Welcome to your Express Backend!',
758
- res,
759
- status: 200
760
- })
761
- })
762
-
763
- export { Home }
764
- `,
765
- file: `${projectName}/src/network/routes/home.ts`
766
- },
767
- index: {
768
- content: `export * from './home'
769
- export * from './user'
770
- `,
771
- file: `${projectName}/src/network/routes/index.ts`
772
- },
773
- user: {
774
- content: `import { Router } from 'express'
775
-
776
- import { response } from 'network/response'
777
- import { UserService } from 'services'
778
- import { idSchema, storeUserSchema, UserDTO } from 'schemas'
779
- import { validatorCompiler } from './utils'
780
-
781
- const User = Router()
782
-
783
- User.route('/users')
784
- .post(
785
- validatorCompiler(storeUserSchema, 'body'),
786
- async (req: CustomRequest, res: CustomResponse): Promise<void> => {
787
- const {
788
- body: { args }
789
- } = req
790
- const us = new UserService({ userDtoWithoutId: args })
791
- const result = await us.process({ type: 'store' })
792
-
793
- response({ error: false, message: result, res, status: 201 })
794
- }
795
- )
796
- .get(async (req: CustomRequest, res: CustomResponse): Promise<void> => {
797
- const us = new UserService()
798
- const result = await us.process({ type: 'getAll' })
799
-
800
- response({ error: false, message: result, res, status: 200 })
801
- })
802
- .delete(async (req: CustomRequest, res: CustomResponse): Promise<void> => {
803
- const us = new UserService()
804
- const result = await us.process({ type: 'deleteAll' })
805
-
806
- response({ error: false, message: result, res, status: 200 })
807
- })
808
-
809
- User.route('/user/:id')
810
- .get(
811
- validatorCompiler(idSchema, 'params'),
812
- async (req: CustomRequest, res: CustomResponse): Promise<void> => {
813
- const {
814
- params: { id }
815
- } = req
816
- const us = new UserService({ id })
817
- const result = await us.process({ type: 'getOne' })
818
-
819
- response({ error: false, message: result, res, status: 200 })
820
- }
821
- )
822
- .patch(
823
- validatorCompiler(idSchema, 'params'),
824
- validatorCompiler(storeUserSchema, 'body'),
825
- async (req: CustomRequest, res: CustomResponse): Promise<void> => {
826
- const {
827
- body: { args },
828
- params: { id }
829
- } = req
830
- const userDto = {
831
- id,
832
- ...args
833
- } as UserDTO
834
- const us = new UserService({ userDto })
835
- const result = await us.process({ type: 'update' })
836
-
837
- response({ error: false, message: result, res, status: 200 })
838
- }
839
- )
840
- .delete(
841
- validatorCompiler(idSchema, 'params'),
842
- async (req: CustomRequest, res: CustomResponse): Promise<void> => {
843
- const {
844
- params: { id }
845
- } = req
846
- const us = new UserService({ id })
847
- const result = await us.process({ type: 'delete' })
848
-
849
- response({ error: false, message: result, res, status: 200 })
850
- }
851
- )
852
-
853
- export { User }
854
- `,
855
- file: `${projectName}/src/network/routes/user.ts`
856
- }
857
- },
858
- 'network/routes/utils': {
859
- index: {
860
- content: `import { NextFunction } from 'express'
861
- import httpErrors from 'http-errors'
862
- import { TObject, TProperties } from '@sinclair/typebox'
863
- import Ajv from 'ajv'
864
-
865
- const ajv = new Ajv({
866
- removeAdditional: true,
867
- useDefaults: true,
868
- coerceTypes: true,
869
- nullable: true
870
- })
871
-
872
- type Middleware = (
873
- req: CustomRequest,
874
- res: CustomResponse,
875
- next: NextFunction
876
- ) => void
877
-
878
- const validatorCompiler = <T extends TProperties>(
879
- schema: TObject<T>,
880
- value: 'body' | 'params'
881
- ): Middleware => {
882
- return (req: CustomRequest, res: CustomResponse, next: NextFunction) => {
883
- const validate = ajv.compile(schema)
884
- const ok = validate(req[value])
885
-
886
- if (!ok && validate.errors) {
887
- const [error] = validate.errors
888
- const errorMessage = \`\${error.dataPath.replace('.', '')} \${error.message}\`
889
-
890
- return next(new httpErrors.UnprocessableEntity(errorMessage))
891
- }
892
-
893
- next()
894
- }
895
- }
896
-
897
- export { validatorCompiler }
898
- `,
899
- file: `${projectName}/src/network/routes/utils/index.ts`
900
- }
901
- },
902
- utils: {
903
- docs: {
904
- content: `{
905
- "openapi": "3.0.0",
906
- "info": {
907
- "title": "${projectName}",
908
- "description": "Documentation of the test",
909
- "contact": {
910
- "email": "${email}"
911
- },
912
- "license": {
913
- "name": "MIT",
914
- "url": "https://opensource.org/licenses/MIT"
915
- },
916
- "version": "${projectVersion}"
917
- },
918
- "servers": [
919
- {
920
- "url": "http://localhost:1996/api",
921
- "description": "${projectName} local API"
922
- }
923
- ],
924
- "tags": [
925
- {
926
- "name": "user",
927
- "description": "Operations related to the user"
928
- }
929
- ],
930
- "paths": {
931
- "/users": {
932
- "post": {
933
- "tags": [
934
- "user"
935
- ],
936
- "summary": "Save a user in the database",
937
- "operationId": "store",
938
- "requestBody": {
939
- "$ref": "#/components/requestBodies/UserDTO"
940
- },
941
- "responses": {
942
- "201": {
943
- "description": "User successfully stored",
944
- "content": {
945
- "application/json": {
946
- "schema": {
947
- "$ref": "#/components/schemas/User"
948
- }
949
- }
950
- }
951
- },
952
- "422": {
953
- "description": "Invalid request format",
954
- "content": {
955
- "application/json": {
956
- "schema": {
957
- "$ref": "#/components/schemas/DefaultError"
958
- }
959
- }
960
- }
961
- },
962
- "500": {
963
- "description": "Internal server error",
964
- "content": {
965
- "application/json": {
966
- "schema": {
967
- "$ref": "#/components/schemas/DefaultError"
968
- }
969
- }
970
- }
971
- }
972
- }
973
- },
974
- "get": {
975
- "tags": [
976
- "user"
977
- ],
978
- "summary": "Get all the users in the database",
979
- "operationId": "getAll",
980
- "responses": {
981
- "200": {
982
- "description": "All the users in the database",
983
- "content": {
984
- "application/json": {
985
- "schema": {
986
- "type": "object",
987
- "properties": {
988
- "error": {
989
- "type": "boolean",
990
- "default": false
991
- },
992
- "message": {
993
- "type": "object",
994
- "properties": {
995
- "result": {
996
- "type": "array",
997
- "items": {
998
- "$ref": "#/components/schemas/User"
999
- }
1000
- }
1001
- }
1002
- }
1003
- }
1004
- }
1005
- }
1006
- }
1007
- },
1008
- "500": {
1009
- "description": "Internal server error",
1010
- "content": {
1011
- "application/json": {
1012
- "schema": {
1013
- "$ref": "#/components/schemas/DefaultError"
1014
- }
1015
- }
1016
- }
1017
- }
1018
- }
1019
- },
1020
- "delete": {
1021
- "tags": [
1022
- "user"
1023
- ],
1024
- "summary": "Delete all the users in the database",
1025
- "operationId": "deleteAll",
1026
- "responses": {
1027
- "200": {
1028
- "description": "All the users in the database",
1029
- "content": {
1030
- "application/json": {
1031
- "schema": {
1032
- "$ref": "#/components/schemas/DefaultSuccess"
1033
- }
1034
- }
1035
- }
1036
- },
1037
- "500": {
1038
- "description": "Internal server error",
1039
- "content": {
1040
- "application/json": {
1041
- "schema": {
1042
- "$ref": "#/components/schemas/DefaultError"
1043
- }
1044
- }
1045
- }
1046
- }
1047
- }
1048
- }
1049
- },
1050
- "/user/{id}": {
1051
- "get": {
1052
- "tags": [
1053
- "user"
1054
- ],
1055
- "summary": "Get an specific user",
1056
- "operationId": "getOne",
1057
- "parameters": [
1058
- {
1059
- "name": "id",
1060
- "in": "path",
1061
- "description": "MongoDB user id",
1062
- "required": true,
1063
- "style": "simple",
1064
- "explode": false,
1065
- "schema": {
1066
- "type": "string"
1067
- }
1068
- }
1069
- ],
1070
- "responses": {
1071
- "200": {
1072
- "description": "User stored in the database",
1073
- "content": {
1074
- "application/json": {
1075
- "schema": {
1076
- "$ref": "#/components/schemas/User"
1077
- }
1078
- }
1079
- }
1080
- },
1081
- "404": {
1082
- "description": "User not found",
1083
- "content": {
1084
- "application/json": {
1085
- "schema": {
1086
- "$ref": "#/components/schemas/DefaultError"
1087
- }
1088
- }
1089
- }
1090
- },
1091
- "422": {
1092
- "description": "Invalid request format",
1093
- "content": {
1094
- "application/json": {
1095
- "schema": {
1096
- "$ref": "#/components/schemas/DefaultError"
1097
- }
1098
- }
1099
- }
1100
- },
1101
- "500": {
1102
- "description": "Internal server error",
1103
- "content": {
1104
- "application/json": {
1105
- "schema": {
1106
- "$ref": "#/components/schemas/DefaultError"
1107
- }
1108
- }
1109
- }
1110
- }
1111
- }
1112
- },
1113
- "patch": {
1114
- "tags": [
1115
- "user"
1116
- ],
1117
- "summary": "Update the user data",
1118
- "operationId": "update",
1119
- "parameters": [
1120
- {
1121
- "name": "id",
1122
- "in": "path",
1123
- "description": "MongoDB user id",
1124
- "required": true,
1125
- "style": "simple",
1126
- "explode": false,
1127
- "schema": {
1128
- "type": "string"
1129
- }
1130
- }
1131
- ],
1132
- "requestBody": {
1133
- "$ref": "#/components/requestBodies/UserDTO"
1134
- },
1135
- "responses": {
1136
- "200": {
1137
- "description": "User successfully updated",
1138
- "content": {
1139
- "application/json": {
1140
- "schema": {
1141
- "$ref": "#/components/schemas/User"
1142
- }
1143
- }
1144
- }
1145
- },
1146
- "404": {
1147
- "description": "User not found",
1148
- "content": {
1149
- "application/json": {
1150
- "schema": {
1151
- "$ref": "#/components/schemas/DefaultError"
1152
- }
1153
- }
1154
- }
1155
- },
1156
- "422": {
1157
- "description": "Invalid request format",
1158
- "content": {
1159
- "application/json": {
1160
- "schema": {
1161
- "$ref": "#/components/schemas/DefaultError"
1162
- }
1163
- }
1164
- }
1165
- },
1166
- "500": {
1167
- "description": "Internal server error",
1168
- "content": {
1169
- "application/json": {
1170
- "schema": {
1171
- "$ref": "#/components/schemas/DefaultError"
1172
- }
1173
- }
1174
- }
1175
- }
1176
- }
1177
- },
1178
- "delete": {
1179
- "tags": [
1180
- "user"
1181
- ],
1182
- "summary": "Delete one user from the database",
1183
- "operationId": "delete",
1184
- "parameters": [
1185
- {
1186
- "name": "id",
1187
- "in": "path",
1188
- "description": "MongoDB user id",
1189
- "required": true,
1190
- "style": "simple",
1191
- "explode": false,
1192
- "schema": {
1193
- "type": "string"
1194
- }
1195
- }
1196
- ],
1197
- "responses": {
1198
- "200": {
1199
- "description": "User successfully deleted",
1200
- "content": {
1201
- "application/json": {
1202
- "schema": {
1203
- "$ref": "#/components/schemas/DefaultSuccess"
1204
- }
1205
- }
1206
- }
1207
- },
1208
- "404": {
1209
- "description": "User not found",
1210
- "content": {
1211
- "application/json": {
1212
- "schema": {
1213
- "$ref": "#/components/schemas/DefaultError"
1214
- }
1215
- }
1216
- }
1217
- },
1218
- "422": {
1219
- "description": "Invalid request format",
1220
- "content": {
1221
- "application/json": {
1222
- "schema": {
1223
- "$ref": "#/components/schemas/DefaultError"
1224
- }
1225
- }
1226
- }
1227
- },
1228
- "500": {
1229
- "description": "Internal server error",
1230
- "content": {
1231
- "application/json": {
1232
- "schema": {
1233
- "$ref": "#/components/schemas/DefaultError"
1234
- }
1235
- }
1236
- }
1237
- }
1238
- }
1239
- }
1240
- }
1241
- },
1242
- "components": {
1243
- "schemas": {
1244
- "User": {
1245
- "type": "object",
1246
- "properties": {
1247
- "id": {
1248
- "type": "string"
1249
- },
1250
- "lastName": {
1251
- "type": "string"
1252
- },
1253
- "name": {
1254
- "type": "string"
1255
- }
1256
- }
1257
- },
1258
- "DefaultSuccess": {
1259
- "type": "object",
1260
- "properties": {
1261
- "error": {
1262
- "type": "boolean",
1263
- "default": false
1264
- },
1265
- "message": {
1266
- "type": "object",
1267
- "properties": {
1268
- "result": {
1269
- "type": "string"
1270
- }
1271
- }
1272
- }
1273
- }
1274
- },
1275
- "DefaultError": {
1276
- "type": "object",
1277
- "properties": {
1278
- "error": {
1279
- "type": "boolean",
1280
- "default": true
1281
- },
1282
- "message": {
1283
- "type": "object",
1284
- "properties": {
1285
- "result": {
1286
- "type": "string"
1287
- }
1288
- }
1289
- }
1290
- }
1291
- }
1292
- },
1293
- "requestBodies": {
1294
- "UserDTO": {
1295
- "description": "User name and last name",
1296
- "content": {
1297
- "application/json": {
1298
- "schema": {
1299
- "type": "object",
1300
- "properties": {
1301
- "args": {
1302
- "type": "object",
1303
- "properties": {
1304
- "name": {
1305
- "type": "string"
1306
- },
1307
- "lastName": {
1308
- "type": "string"
1309
- }
1310
- }
1311
- }
1312
- }
1313
- }
1314
- }
1315
- },
1316
- "required": true
1317
- }
1318
- }
1319
- }
1320
- }`,
1321
- file: `${projectName}/src/utils/docs.json`
1322
- },
1323
- index: {
1324
- content: "export { default as docs } from './docs.json'\n",
1325
- file: `${projectName}/src/utils/index.ts`
1326
- }
1327
- }
1328
- }
1329
-
1330
- const fastifyData = {
1331
- network: {
1332
- response: {
1333
- content: `import { FastifyReply } from 'fastify'
1334
-
1335
- const response = ({
1336
- error,
1337
- message,
1338
- reply,
1339
- status
1340
- }: {
1341
- error: boolean
1342
- message: unknown
1343
- reply: FastifyReply
1344
- status: number
1345
- }): void => {
1346
- reply.code(status).send({ error, message })
1347
- }
1348
-
1349
- export { response }
1350
- `,
1351
- file: `${projectName}/src/network/response.ts`
1352
- },
1353
- router: {
1354
- content: `import { FastifyInstance } from 'fastify'
1355
- import { HttpError } from 'http-errors'
1356
-
1357
- import { response } from './response'
1358
- import { Home, User, Docs } from './routes'
1359
-
1360
- const routers = [Docs, User]
1361
-
1362
- const applyRoutes = (app: FastifyInstance): void => {
1363
- Home(app)
1364
- routers.forEach(router => router(app))
1365
-
1366
- // Handling 404 error
1367
- app.setNotFoundHandler((request, reply) => {
1368
- response({
1369
- error: true,
1370
- message: 'This route does not exists',
1371
- reply,
1372
- status: 404
1373
- })
1374
- })
1375
- app.setErrorHandler<HttpError>((error, request, reply) => {
1376
- response({
1377
- error: true,
1378
- message: error.message,
1379
- reply,
1380
- status: error.status ?? 500
1381
- })
1382
- })
1383
- }
1384
-
1385
- export { applyRoutes }
1386
- `,
1387
- file: `${projectName}/src/network/router.ts`
1388
- },
1389
- server: {
1390
- content: `import Fastify, { FastifyInstance } from 'fastify'
1391
- import mongoose from 'mongoose'
1392
-
1393
- import { applyRoutes } from './router'
1394
-
1395
- const PORT = process.env.PORT ?? '1996'
1396
-
1397
- class Server {
1398
- #app: FastifyInstance
1399
- #connection: mongoose.Connection | undefined
1400
-
1401
- constructor() {
1402
- this.#app = Fastify({ logger: true })
1403
- this.#config()
1404
- }
1405
-
1406
- #config() {
1407
- this.#app.register(require('fastify-cors'), {})
1408
- this.#app.addHook('preHandler', (req, reply, done) => {
1409
- reply.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE')
1410
- reply.header('Access-Control-Allow-Origin', '*')
1411
- reply.header(
1412
- 'Access-Control-Allow-Headers',
1413
- 'Authorization, Content-Type'
1414
- )
1415
- done()
1416
- })
1417
- applyRoutes(this.#app)
1418
- }
1419
-
1420
- async #mongo(): Promise<void> {
1421
- this.#connection = mongoose.connection
1422
- const connection = {
1423
- keepAlive: true,
1424
- useNewUrlParser: true,
1425
- useUnifiedTopology: true
1426
- }
1427
- this.#connection.on('connected', () => {
1428
- this.#app.log.info('Mongo connection established.')
1429
- })
1430
- this.#connection.on('reconnected', () => {
1431
- this.#app.log.info('Mongo connection reestablished')
1432
- })
1433
- this.#connection.on('disconnected', () => {
1434
- this.#app.log.info('Mongo connection disconnected')
1435
- this.#app.log.info('Trying to reconnected to Mongo...')
1436
- setTimeout(() => {
1437
- mongoose.connect(process.env.MONGO_URI as string, {
1438
- ...connection,
1439
- connectTimeoutMS: 3000,
1440
- socketTimeoutMS: 3000
1441
- })
1442
- }, 3000)
1443
- })
1444
- this.#connection.on('close', () => {
1445
- this.#app.log.info('Mongo connection closed')
1446
- })
1447
- this.#connection.on('error', (e: Error) => {
1448
- this.#app.log.info('Mongo connection error:')
1449
- this.#app.log.error(e)
1450
- })
1451
- await mongoose.connect(process.env.MONGO_URI as string, connection)
1452
- }
1453
-
1454
- public async start(): Promise<void> {
1455
- try {
1456
- await this.#app.listen(PORT)
1457
- this.#mongo()
1458
- } catch (e) {
1459
- console.error(e)
1460
- }
1461
- }
1462
- }
1463
-
1464
- const server = new Server()
1465
-
1466
- export { server as Server }
1467
- `,
1468
- file: `${projectName}/src/network/server.ts`
1469
- }
1470
- },
1471
- 'network/routes': {
1472
- docs: {
1473
- content: `import { FastifyInstance } from 'fastify'
1474
- import fastifySwagger from 'fastify-swagger'
1475
-
1476
- const Docs = (app: FastifyInstance, prefix = '/api'): void => {
1477
- app.register(fastifySwagger, {
1478
- routePrefix: \`\${prefix}/docs\`,
1479
- openapi: {
1480
- info: {
1481
- title: 'Test swagger',
1482
- description: 'Testing the Fastify swagger API',
1483
- version: '0.1.0',
1484
- contact: {
1485
- email: 'sluzquinosa@uni.pe'
1486
- },
1487
- license: {
1488
- name: 'MIT',
1489
- url: 'https://opensource.org/licenses/MIT'
1490
- }
1491
- },
1492
- servers: [
1493
- {
1494
- url: 'http://localhost:1996/api',
1495
- description: 'test-fastify local API'
1496
- }
1497
- ],
1498
- tags: [
1499
- {
1500
- name: 'user',
1501
- description: 'User related endpoints'
1502
- }
1503
- ]
1504
- },
1505
- exposeRoute: true
1506
- })
1507
- }
1508
-
1509
- export { Docs }
1510
- `,
1511
- file: `${projectName}/src/network/routes/docs.ts`
1512
- },
1513
- home: {
1514
- content: `import { FastifyInstance } from 'fastify'
1515
- import { response } from 'network/response'
1516
-
1517
- const Home = (app: FastifyInstance, prefix = '/'): void => {
1518
- app.get(\`\${prefix}\`, (request, reply) => {
1519
- response({
1520
- error: false,
1521
- message: 'Welcome to your Fastify Backend!',
1522
- reply,
1523
- status: 200
1524
- })
1525
- })
1526
- }
1527
-
1528
- export { Home }
1529
- `,
1530
- file: `${projectName}/src/network/routes/home.ts`
1531
- },
1532
- index: {
1533
- content: `export * from './home'
1534
- export * from './user'
1535
- export * from './docs'
1536
- `,
1537
- file: `${projectName}/src/network/routes/index.ts`
1538
- },
1539
- user: {
1540
- content: `import { FastifyInstance } from 'fastify'
1541
- import { Type } from '@sinclair/typebox'
1542
-
1543
- import { response } from 'network/response'
1544
- import {
1545
- userDto,
1546
- idSchema,
1547
- IdSchema,
1548
- storeUserSchema,
1549
- StoreUser
1550
- } from 'schemas'
1551
- import { UserService } from 'services'
1552
- import { validatorCompiler } from './utils'
1553
-
1554
- const User = (app: FastifyInstance, prefix = '/api'): void => {
1555
- app
1556
- .post<{ Body: StoreUser }>(
1557
- \`\${prefix}/users\`,
1558
- {
1559
- schema: {
1560
- body: storeUserSchema,
1561
- response: {
1562
- 200: {
1563
- error: {
1564
- type: 'boolean'
1565
- },
1566
- message: userDto
1567
- }
1568
- },
1569
- tags: ['user']
1570
- },
1571
- validatorCompiler
1572
- },
1573
- async (request, reply) => {
1574
- const {
1575
- body: {
1576
- args: { lastName, name }
1577
- }
1578
- } = request
1579
- const us = new UserService({
1580
- userDtoWithoutId: { lastName, name }
1581
- })
1582
- const user = await us.process({ type: 'store' })
1583
-
1584
- response({
1585
- error: false,
1586
- message: user,
1587
- reply,
1588
- status: 201
1589
- })
1590
- }
1591
- )
1592
- .get(
1593
- \`\${prefix}/users\`,
1594
- {
1595
- schema: {
1596
- response: {
1597
- 200: {
1598
- error: {
1599
- type: 'boolean'
1600
- },
1601
- message: Type.Array(userDto)
1602
- }
1603
- },
1604
- tags: ['user']
1605
- }
1606
- },
1607
- async (request, reply) => {
1608
- const us = new UserService()
1609
- const users = await us.process({ type: 'getAll' })
1610
-
1611
- response({
1612
- error: false,
1613
- message: users,
1614
- reply,
1615
- status: 200
1616
- })
1617
- }
1618
- )
1619
- .delete(
1620
- \`\${prefix}/users\`,
1621
- {
1622
- schema: {
1623
- response: {
1624
- 200: {
1625
- error: {
1626
- type: 'boolean'
1627
- },
1628
- message: {
1629
- type: 'string'
1630
- }
1631
- }
1632
- },
1633
- tags: ['user']
1634
- }
1635
- },
1636
- async (request, reply) => {
1637
- const us = new UserService()
1638
- const result = await us.process({ type: 'deleteAll' })
1639
-
1640
- response({
1641
- error: false,
1642
- message: result,
1643
- reply,
1644
- status: 200
1645
- })
1646
- }
1647
- )
1648
- .get<{ Params: IdSchema }>(
1649
- \`\${prefix}/user/:id\`,
1650
- {
1651
- schema: {
1652
- params: idSchema,
1653
- response: {
1654
- 200: {
1655
- error: {
1656
- type: 'boolean'
1657
- },
1658
- message: userDto
1659
- }
1660
- },
1661
- tags: ['user']
1662
- },
1663
- validatorCompiler
1664
- },
1665
- async (request, reply) => {
1666
- const {
1667
- params: { id }
1668
- } = request
1669
- const us = new UserService({ id })
1670
- const user = await us.process({ type: 'getOne' })
1671
-
1672
- response({
1673
- error: false,
1674
- message: user,
1675
- reply,
1676
- status: 200
1677
- })
1678
- }
1679
- )
1680
- .patch<{ Body: StoreUser; Params: IdSchema }>(
1681
- \`\${prefix}/user/:id\`,
1682
- {
1683
- schema: {
1684
- body: storeUserSchema,
1685
- params: idSchema,
1686
- response: {
1687
- 200: {
1688
- error: {
1689
- type: 'boolean'
1690
- },
1691
- message: userDto
1692
- }
1693
- },
1694
- tags: ['user']
1695
- }
1696
- },
1697
- async (request, reply) => {
1698
- const {
1699
- body: {
1700
- args: { name, lastName }
1701
- },
1702
- params: { id }
1703
- } = request
1704
- const us = new UserService({
1705
- userDto: { name, lastName, id }
1706
- })
1707
- const user = await us.process({ type: 'update' })
1708
-
1709
- response({
1710
- error: false,
1711
- message: user,
1712
- reply,
1713
- status: 200
1714
- })
1715
- }
1716
- )
1717
- .delete<{ Params: IdSchema }>(
1718
- \`\${prefix}/user/:id\`,
1719
- {
1720
- schema: {
1721
- params: idSchema,
1722
- response: {
1723
- 200: {
1724
- error: {
1725
- type: 'boolean'
1726
- },
1727
- message: {
1728
- type: 'string'
1729
- }
1730
- }
1731
- },
1732
- tags: ['user']
1733
- }
1734
- },
1735
- async (request, reply) => {
1736
- const {
1737
- params: { id }
1738
- } = request
1739
- const us = new UserService({ id })
1740
- const result = await us.process({ type: 'delete' })
1741
-
1742
- response({
1743
- error: false,
1744
- message: result,
1745
- reply,
1746
- status: 200
1747
- })
1748
- }
1749
- )
1750
- }
1751
-
1752
- export { User }
1753
- `,
1754
- file: `${projectName}/src/network/routes/user.ts`
1755
- }
1756
- },
1757
- 'network/routes/utils': {
1758
- index: {
1759
- content: `/* eslint-disable @typescript-eslint/no-explicit-any */
1760
- import {
1761
- FastifyRouteSchemaDef,
1762
- FastifyValidationResult
1763
- } from 'fastify/types/schema'
1764
- import httpErrors from 'http-errors'
1765
- import Ajv from 'ajv'
1766
-
1767
- const ajv = new Ajv({
1768
- removeAdditional: true,
1769
- useDefaults: true,
1770
- coerceTypes: true,
1771
- nullable: true
1772
- })
1773
-
1774
- const validatorCompiler = ({
1775
- schema
1776
- }: FastifyRouteSchemaDef<any>): FastifyValidationResult => {
1777
- const validate = ajv.compile(schema)
1778
-
1779
- return (data: unknown): boolean => {
1780
- const ok = validate(data)
1781
-
1782
- if (!ok && validate.errors) {
1783
- const [error] = validate.errors
1784
- const errorMessage = \`\${error.dataPath.replace('.', '')} \${error.message}\`
1785
-
1786
- throw new httpErrors.UnprocessableEntity(errorMessage)
1787
- }
1788
-
1789
- return true
1790
- }
1791
- }
1792
-
1793
- export { validatorCompiler }
1794
- `,
1795
- file: `${projectName}/src/network/routes/utils/index.ts`
1796
- }
1797
- }
1798
- }
1799
-
1800
- const expressFolders = `${projectName}/src/utils \
1801
- ${projectName}/src/@types/custom`
1802
-
1803
- const createFoldersCommands = `mkdir ${projectName}/src \
1804
- ${projectName}/src/@types \
1805
- ${projectName}/src/@types/models \
1806
- ${projectName}/src/database \
1807
- ${projectName}/src/database/mongo \
1808
- ${projectName}/src/database/mongo/models \
1809
- ${projectName}/src/database/mongo/queries \
1810
- ${projectName}/src/network \
1811
- ${projectName}/src/network/routes \
1812
- ${projectName}/src/network/routes/utils \
1813
- ${projectName}/src/schemas \
1814
- ${projectName}/src/services \
1815
- ${projectName}/src/services/utils \
1816
- ${projectName}/src/services/utils/messages \
1817
- ${fastify ? '' : `${expressFolders}`}
1818
- `
1819
-
1820
- if (os.platform() === 'win32')
1821
- await exec(createFoldersCommands.replaceAll('/', '\\'))
1822
- else await exec(createFoldersCommands)
1823
-
1824
- // /@types
1825
- await writeFile(data['@types'].index.file, data['@types'].index.content)
1826
-
1827
- // /@types/models
1828
- await writeFile(
1829
- data['@types/models'].user.file,
1830
- data['@types/models'].user.content
1831
- )
1832
-
1833
- // /database
1834
- await writeFile(data.database.index.file, data.database.index.content)
1835
- await writeFile(
1836
- data['database/mongo'].index.file,
1837
- data['database/mongo'].index.content
1838
- )
1839
- await writeFile(
1840
- data['database/mongo/models'].index.file,
1841
- data['database/mongo/models'].index.content
1842
- )
1843
- await writeFile(
1844
- data['database/mongo/models'].user.file,
1845
- data['database/mongo/models'].user.content
1846
- )
1847
- await writeFile(
1848
- data['database/mongo/queries'].index.file,
1849
- data['database/mongo/queries'].index.content
1850
- )
1851
- await writeFile(
1852
- data['database/mongo/queries'].user.file,
1853
- data['database/mongo/queries'].user.content
1854
- )
1855
-
1856
- // /schemas
1857
- await writeFile(data.schemas.user.file, data.schemas.user.content)
1858
- await writeFile(data.schemas.index.file, data.schemas.index.content)
1859
-
1860
- // /services
1861
- await writeFile(data.services.user.file, data.services.user.content)
1862
- await writeFile(data.services.index.file, data.services.index.content)
1863
-
1864
- // /services/utils
1865
- await writeFile(
1866
- data['services/utils'].index.file,
1867
- data['services/utils'].index.content
1868
- )
1869
-
1870
- // /services/utils/messages
1871
- await writeFile(
1872
- data['services/utils/messages'].user.file,
1873
- data['services/utils/messages'].user.content
1874
- )
1875
- await writeFile(
1876
- data['services/utils/messages'].index.file,
1877
- data['services/utils/messages'].index.content
1878
- )
1879
-
1880
- // /network
1881
- await writeFile(data.network.index.file, data.network.index.content)
1882
-
1883
- // /test
1884
- await writeFile(data.test.index.file, data.test.index.content)
1885
-
1886
- // .env
1887
- await writeFile(data['.env'].file, data['.env'].content)
1888
-
1889
- // index
1890
- await writeFile(data.index.file, data.index.content)
1891
-
1892
- if (fastify) {
1893
- // /network
1894
- await writeFile(
1895
- fastifyData.network.response.file,
1896
- fastifyData.network.response.content
1897
- )
1898
- await writeFile(
1899
- fastifyData.network.router.file,
1900
- fastifyData.network.router.content
1901
- )
1902
- await writeFile(
1903
- fastifyData.network.server.file,
1904
- fastifyData.network.server.content
1905
- )
1906
-
1907
- // /network/routes
1908
- await writeFile(
1909
- fastifyData['network/routes'].docs.file,
1910
- fastifyData['network/routes'].docs.content
1911
- )
1912
- await writeFile(
1913
- fastifyData['network/routes'].home.file,
1914
- fastifyData['network/routes'].home.content
1915
- )
1916
- await writeFile(
1917
- fastifyData['network/routes'].user.file,
1918
- fastifyData['network/routes'].user.content
1919
- )
1920
- await writeFile(
1921
- fastifyData['network/routes'].index.file,
1922
- fastifyData['network/routes'].index.content
1923
- )
1924
-
1925
- // /network/routes/utils
1926
- await writeFile(
1927
- fastifyData['network/routes/utils'].index.file,
1928
- fastifyData['network/routes/utils'].index.content
1929
- )
1930
- } else {
1931
- // /@types/custom
1932
- await writeFile(
1933
- expressData['@types/custom'].request.file,
1934
- expressData['@types/custom'].request.content
1935
- )
1936
- await writeFile(
1937
- expressData['@types/custom'].response.file,
1938
- expressData['@types/custom'].response.content
1939
- )
1940
-
1941
- // /network
1942
- await writeFile(
1943
- expressData.network.response.file,
1944
- expressData.network.response.content
1945
- )
1946
- await writeFile(
1947
- expressData.network.router.file,
1948
- expressData.network.router.content
1949
- )
1950
- await writeFile(
1951
- expressData.network.server.file,
1952
- expressData.network.server.content
1953
- )
1954
-
1955
- // /network/routes
1956
- await writeFile(
1957
- expressData['network/routes'].home.file,
1958
- expressData['network/routes'].home.content
1959
- )
1960
- await writeFile(
1961
- expressData['network/routes'].user.file,
1962
- expressData['network/routes'].user.content
1963
- )
1964
- await writeFile(
1965
- expressData['network/routes'].index.file,
1966
- expressData['network/routes'].index.content
1967
- )
1968
-
1969
- // /network/routes/utils
1970
- await writeFile(
1971
- expressData['network/routes/utils'].index.file,
1972
- expressData['network/routes/utils'].index.content
1973
- )
1974
-
1975
- // /utils
1976
- await writeFile(expressData.utils.docs.file, expressData.utils.docs.content)
1977
- await writeFile(
1978
- expressData.utils.index.file,
1979
- expressData.utils.index.content
1980
- )
1981
- }
1982
- }