@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.
@@ -0,0 +1,906 @@
1
+ const { platform } = require('os')
2
+ const { promisify } = require('util')
3
+ const exec = promisify(require('child_process').exec)
4
+ const writeFile = require('../../utils/writeFile')
5
+
6
+ /**
7
+ * @param {Object} args
8
+ * @param {String} args.projectName
9
+ */
10
+ const expressRestNetwork = async ({ projectName }) => {
11
+ const createFoldersCommand = `mkdir ${projectName}/src/network/routes/utils`
12
+
13
+ if (platform() === 'win32')
14
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
15
+ else await exec(createFoldersCommand)
16
+
17
+ const network = {
18
+ response: {
19
+ content: `interface ResponseProps {
20
+ error: boolean
21
+ message: unknown
22
+ res: CustomResponse
23
+ status: number
24
+ }
25
+
26
+ const response = ({ error, message, res, status }: ResponseProps): void => {
27
+ res.status(status).send({ error, message })
28
+ }
29
+
30
+ export { response }
31
+ `,
32
+ file: `${projectName}/src/network/response.ts`
33
+ },
34
+ router: {
35
+ content: `import { Application, Response, Request, Router, NextFunction } from 'express'
36
+ import swaggerUi from 'swagger-ui-express'
37
+ import httpErrors from 'http-errors'
38
+
39
+ import { response } from './response'
40
+ import { Home, User } from './routes'
41
+ import { docs } from 'utils'
42
+
43
+ const routers = [User]
44
+ const applyRoutes = (app: Application): void => {
45
+ app.use('/', Home)
46
+ app.use('/api/docs', swaggerUi.serve, swaggerUi.setup(docs))
47
+ routers.forEach((router: Router): Application => app.use('/api', router))
48
+
49
+ // Handling 404 error
50
+ app.use((req, res, next) => {
51
+ next(new httpErrors.NotFound('This route does not exists'))
52
+ })
53
+ app.use(
54
+ (
55
+ error: httpErrors.HttpError,
56
+ req: Request,
57
+ res: Response,
58
+ next: NextFunction
59
+ ) => {
60
+ response({
61
+ error: true,
62
+ message: error.message,
63
+ res,
64
+ status: error.status
65
+ })
66
+ next()
67
+ }
68
+ )
69
+ }
70
+
71
+ export { applyRoutes }
72
+ `,
73
+ file: `${projectName}/src/network/router.ts`
74
+ },
75
+ server: {
76
+ content: `import express from 'express'
77
+ import mongoose from 'mongoose'
78
+ import morgan from 'morgan'
79
+ import cors from 'cors'
80
+
81
+ import { applyRoutes } from './router'
82
+
83
+ const PORT = (process.env.PORT as string) || '1996'
84
+
85
+ class Server {
86
+ #app: express.Application
87
+ #connection: mongoose.Connection | undefined
88
+
89
+ constructor() {
90
+ this.#app = express()
91
+ this.#config()
92
+ }
93
+
94
+ #config() {
95
+ this.#app.use(cors())
96
+ this.#app.use(morgan('dev'))
97
+ this.#app.use(express.json())
98
+ this.#app.use(express.urlencoded({ extended: false }))
99
+ this.#app.use(
100
+ (
101
+ req: express.Request,
102
+ res: express.Response,
103
+ next: express.NextFunction
104
+ ) => {
105
+ res.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE')
106
+ res.header('Access-Control-Allow-Origin', '*')
107
+ res.header(
108
+ 'Access-Control-Allow-Headers',
109
+ 'Authorization, Content-Type'
110
+ )
111
+ next()
112
+ }
113
+ )
114
+
115
+ applyRoutes(this.#app)
116
+ }
117
+
118
+ async #mongo(): Promise<void> {
119
+ this.#connection = mongoose.connection
120
+ const connection = {
121
+ keepAlive: true,
122
+ useNewUrlParser: true,
123
+ useUnifiedTopology: true
124
+ }
125
+ this.#connection.on('connected', () => {
126
+ console.log('Mongo connection established.')
127
+ })
128
+ this.#connection.on('reconnected', () => {
129
+ console.log('Mongo connection reestablished')
130
+ })
131
+ this.#connection.on('disconnected', () => {
132
+ console.log('Mongo connection disconnected')
133
+ console.log('Trying to reconnected to Mongo...')
134
+ setTimeout(() => {
135
+ mongoose.connect(process.env.MONGO_URI as string, {
136
+ ...connection,
137
+ connectTimeoutMS: 3000,
138
+ socketTimeoutMS: 3000
139
+ })
140
+ }, 3000)
141
+ })
142
+ this.#connection.on('close', () => {
143
+ console.log('Mongo connection closed')
144
+ })
145
+ this.#connection.on('error', (e: Error) => {
146
+ console.log('Mongo connection error:')
147
+ console.error(e)
148
+ })
149
+ await mongoose.connect(process.env.MONGO_URI as string, connection)
150
+ }
151
+
152
+ public start(): void {
153
+ this.#app.listen(PORT, () => {
154
+ console.log(\`Server running at port \${PORT}\`)
155
+ })
156
+
157
+ try {
158
+ this.#mongo()
159
+ } catch (e) {
160
+ console.error(e)
161
+ }
162
+ }
163
+ }
164
+
165
+ const server = new Server()
166
+
167
+ export { server as Server }
168
+ `,
169
+ file: `${projectName}/src/network/server.ts`
170
+ },
171
+ routes: {
172
+ home: {
173
+ content: `import { Response, Request, Router } from 'express'
174
+
175
+ import { response } from 'network/response'
176
+
177
+ const Home = Router()
178
+
179
+ Home.route('').get((req: Request, res: Response) => {
180
+ response({
181
+ error: false,
182
+ message: 'Welcome to your Express Backend!',
183
+ res,
184
+ status: 200
185
+ })
186
+ })
187
+
188
+ export { Home }
189
+ `,
190
+ file: `${projectName}/src/network/routes/home.ts`
191
+ },
192
+ index: {
193
+ content: `export * from './home'
194
+ export * from './user'
195
+ `,
196
+ file: `${projectName}/src/network/routes/index.ts`
197
+ },
198
+ user: {
199
+ content: `import { NextFunction, Router } from 'express'
200
+
201
+ import { response } from 'network/response'
202
+ import { UserService } from 'services'
203
+ import { idSchema, storeUserSchema, UserDTO } from 'schemas'
204
+ import { validatorCompiler } from './utils'
205
+
206
+ const User = Router()
207
+
208
+ User.route('/users')
209
+ .post(
210
+ validatorCompiler(storeUserSchema, 'body'),
211
+ async (
212
+ req: CustomRequest,
213
+ res: CustomResponse,
214
+ next: NextFunction
215
+ ): Promise<void> => {
216
+ try {
217
+ const {
218
+ body: { args }
219
+ } = req
220
+ const us = new UserService({ userDtoWithoutId: args })
221
+ const result = await us.process({ type: 'store' })
222
+
223
+ response({ error: false, message: result, res, status: 201 })
224
+ } catch (error) {
225
+ next(error)
226
+ }
227
+ }
228
+ )
229
+ .get(
230
+ async (
231
+ req: CustomRequest,
232
+ res: CustomResponse,
233
+ next: NextFunction
234
+ ): Promise<void> => {
235
+ try {
236
+ const us = new UserService()
237
+ const result = await us.process({ type: 'getAll' })
238
+
239
+ response({ error: false, message: result, res, status: 200 })
240
+ } catch (error) {
241
+ next(error)
242
+ }
243
+ }
244
+ )
245
+ .delete(
246
+ async (
247
+ req: CustomRequest,
248
+ res: CustomResponse,
249
+ next: NextFunction
250
+ ): Promise<void> => {
251
+ try {
252
+ const us = new UserService()
253
+ const result = await us.process({ type: 'deleteAll' })
254
+
255
+ response({ error: false, message: result, res, status: 200 })
256
+ } catch (error) {
257
+ next(error)
258
+ }
259
+ }
260
+ )
261
+
262
+ User.route('/user/:id')
263
+ .get(
264
+ validatorCompiler(idSchema, 'params'),
265
+ async (
266
+ req: CustomRequest,
267
+ res: CustomResponse,
268
+ next: NextFunction
269
+ ): Promise<void> => {
270
+ try {
271
+ const {
272
+ params: { id }
273
+ } = req
274
+ const us = new UserService({ id })
275
+ const result = await us.process({ type: 'getOne' })
276
+
277
+ response({ error: false, message: result, res, status: 200 })
278
+ } catch (error) {
279
+ next(error)
280
+ }
281
+ }
282
+ )
283
+ .patch(
284
+ validatorCompiler(idSchema, 'params'),
285
+ validatorCompiler(storeUserSchema, 'body'),
286
+ async (
287
+ req: CustomRequest,
288
+ res: CustomResponse,
289
+ next: NextFunction
290
+ ): Promise<void> => {
291
+ try {
292
+ const {
293
+ body: { args },
294
+ params: { id }
295
+ } = req
296
+ const userDto = {
297
+ id,
298
+ ...args
299
+ } as UserDTO
300
+ const us = new UserService({ userDto })
301
+ const result = await us.process({ type: 'update' })
302
+
303
+ response({ error: false, message: result, res, status: 200 })
304
+ } catch (error) {
305
+ next(error)
306
+ }
307
+ }
308
+ )
309
+ .delete(
310
+ validatorCompiler(idSchema, 'params'),
311
+ async (
312
+ req: CustomRequest,
313
+ res: CustomResponse,
314
+ next: NextFunction
315
+ ): Promise<void> => {
316
+ try {
317
+ const {
318
+ params: { id }
319
+ } = req
320
+ const us = new UserService({ id })
321
+ const result = await us.process({ type: 'delete' })
322
+
323
+ response({ error: false, message: result, res, status: 200 })
324
+ } catch (error) {
325
+ next(error)
326
+ }
327
+ }
328
+ )
329
+
330
+ export { User }
331
+ `,
332
+ file: `${projectName}/src/network/routes/user.ts`
333
+ },
334
+ utils: {
335
+ index: {
336
+ content: `import { NextFunction } from 'express'
337
+ import httpErrors from 'http-errors'
338
+ import { TObject, TProperties } from '@sinclair/typebox'
339
+ import Ajv from 'ajv'
340
+
341
+ const ajv = new Ajv({
342
+ removeAdditional: true,
343
+ useDefaults: true,
344
+ coerceTypes: true,
345
+ nullable: true
346
+ })
347
+
348
+ type Middleware = (
349
+ req: CustomRequest,
350
+ res: CustomResponse,
351
+ next: NextFunction
352
+ ) => void
353
+
354
+ const validatorCompiler = <T extends TProperties>(
355
+ schema: TObject<T>,
356
+ value: 'body' | 'params'
357
+ ): Middleware => {
358
+ return (req: CustomRequest, res: CustomResponse, next: NextFunction) => {
359
+ const validate = ajv.compile(schema)
360
+ const ok = validate(req[value])
361
+
362
+ if (!ok && validate.errors) {
363
+ const [error] = validate.errors
364
+ const errorMessage = \`\${error.dataPath.replace('.', '')} \${error.message}\`
365
+
366
+ return next(new httpErrors.UnprocessableEntity(errorMessage))
367
+ }
368
+
369
+ next()
370
+ }
371
+ }
372
+
373
+ export { validatorCompiler }
374
+ `,
375
+ file: `${projectName}/src/network/routes/utils/index.ts`
376
+ }
377
+ }
378
+ }
379
+ }
380
+
381
+ await writeFile(network.response.file, network.response.content)
382
+ await writeFile(network.router.file, network.router.content)
383
+ await writeFile(network.server.file, network.server.content)
384
+ await writeFile(network.routes.home.file, network.routes.home.content)
385
+ await writeFile(network.routes.index.file, network.routes.index.content)
386
+ await writeFile(network.routes.user.file, network.routes.user.content)
387
+ await writeFile(
388
+ network.routes.utils.index.file,
389
+ network.routes.utils.index.content
390
+ )
391
+ }
392
+
393
+ /**
394
+ * @param {Object} args
395
+ * @param {String} args.projectName
396
+ */
397
+ const fastifyRestNetwork = async ({ projectName }) => {
398
+ const createFoldersCommand = `mkdir ${projectName}/src/network/utils`
399
+
400
+ if (platform() === 'win32')
401
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
402
+ else await exec(createFoldersCommand)
403
+
404
+ const network = {
405
+ response: {
406
+ content: `import { FastifyReply } from 'fastify'
407
+
408
+ const response = ({
409
+ error,
410
+ message,
411
+ reply,
412
+ status
413
+ }: {
414
+ error: boolean
415
+ message: unknown
416
+ reply: FastifyReply
417
+ status: number
418
+ }): void => {
419
+ reply.code(status).send({ error, message })
420
+ }
421
+
422
+ export { response }
423
+ `,
424
+ file: `${projectName}/src/network/response.ts`
425
+ },
426
+ router: {
427
+ content: `import { FastifyInstance } from 'fastify'
428
+ import { HttpError } from 'http-errors'
429
+
430
+ import { response } from './response'
431
+ import { Home, User, Docs } from './routes'
432
+
433
+ const routers = [Docs, User]
434
+
435
+ const applyRoutes = (app: FastifyInstance): void => {
436
+ Home(app)
437
+ routers.forEach(router => router(app))
438
+
439
+ // Handling 404 error
440
+ app.setNotFoundHandler((request, reply) => {
441
+ response({
442
+ error: true,
443
+ message: 'This route does not exists',
444
+ reply,
445
+ status: 404
446
+ })
447
+ })
448
+ app.setErrorHandler<HttpError>((error, request, reply) => {
449
+ response({
450
+ error: true,
451
+ message: error.message,
452
+ reply,
453
+ status: error.status ?? 500
454
+ })
455
+ })
456
+ }
457
+
458
+ export { applyRoutes }
459
+ `,
460
+ file: `${projectName}/src/network/router.ts`
461
+ },
462
+ server: {
463
+ content: `import fastify, { FastifyInstance } from 'fastify'
464
+ import mongoose from 'mongoose'
465
+
466
+ import { applyRoutes } from './router'
467
+ import { validatorCompiler } from './utils'
468
+
469
+ const PORT = process.env.PORT ?? '1996'
470
+
471
+ class Server {
472
+ #app: FastifyInstance
473
+ #connection: mongoose.Connection | undefined
474
+
475
+ constructor() {
476
+ this.#app = fastify({ logger: { prettyPrint: true } })
477
+ this.#config()
478
+ }
479
+
480
+ #config() {
481
+ this.#app.register(require('fastify-cors'), {})
482
+ this.#app.addHook('preHandler', (req, reply, done) => {
483
+ reply.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE')
484
+ reply.header('Access-Control-Allow-Origin', '*')
485
+ reply.header(
486
+ 'Access-Control-Allow-Headers',
487
+ 'Authorization, Content-Type'
488
+ )
489
+ done()
490
+ })
491
+ this.#app.setValidatorCompiler(validatorCompiler)
492
+ applyRoutes(this.#app)
493
+ }
494
+
495
+ async #mongo(): Promise<void> {
496
+ this.#connection = mongoose.connection
497
+ const connection = {
498
+ keepAlive: true,
499
+ useNewUrlParser: true,
500
+ useUnifiedTopology: true
501
+ }
502
+ this.#connection.on('connected', () => {
503
+ this.#app.log.info('Mongo connection established.')
504
+ })
505
+ this.#connection.on('reconnected', () => {
506
+ this.#app.log.info('Mongo connection reestablished')
507
+ })
508
+ this.#connection.on('disconnected', () => {
509
+ this.#app.log.info('Mongo connection disconnected')
510
+ this.#app.log.info('Trying to reconnected to Mongo...')
511
+ setTimeout(() => {
512
+ mongoose.connect(process.env.MONGO_URI as string, {
513
+ ...connection,
514
+ connectTimeoutMS: 3000,
515
+ socketTimeoutMS: 3000
516
+ })
517
+ }, 3000)
518
+ })
519
+ this.#connection.on('close', () => {
520
+ this.#app.log.info('Mongo connection closed')
521
+ })
522
+ this.#connection.on('error', (e: Error) => {
523
+ this.#app.log.info('Mongo connection error:')
524
+ this.#app.log.error(e)
525
+ })
526
+ await mongoose.connect(process.env.MONGO_URI as string, connection)
527
+ }
528
+
529
+ public async start(): Promise<void> {
530
+ try {
531
+ await this.#app.listen(PORT)
532
+ this.#mongo()
533
+ } catch (e) {
534
+ console.error(e)
535
+ }
536
+ }
537
+ }
538
+
539
+ const server = new Server()
540
+
541
+ export { server as Server }
542
+ `,
543
+ file: `${projectName}/src/network/server.ts`
544
+ },
545
+ routes: {
546
+ docs: {
547
+ content: `import { FastifyInstance } from 'fastify'
548
+ import fastifySwagger from 'fastify-swagger'
549
+
550
+ const Docs = (app: FastifyInstance, prefix = '/api'): void => {
551
+ app.register(fastifySwagger, {
552
+ routePrefix: \`\${prefix}/docs\`,
553
+ openapi: {
554
+ info: {
555
+ title: 'Test swagger',
556
+ description: 'Testing the Fastify swagger API',
557
+ version: '0.1.0',
558
+ contact: {
559
+ email: 'sluzquinosa@uni.pe'
560
+ },
561
+ license: {
562
+ name: 'MIT',
563
+ url: 'https://opensource.org/licenses/MIT'
564
+ }
565
+ },
566
+ servers: [
567
+ {
568
+ url: 'http://localhost:1996/api',
569
+ description: 'test-fastify local API'
570
+ }
571
+ ],
572
+ tags: [
573
+ {
574
+ name: 'user',
575
+ description: 'User related endpoints'
576
+ }
577
+ ]
578
+ },
579
+ exposeRoute: true
580
+ })
581
+ }
582
+
583
+ export { Docs }
584
+ `,
585
+ file: `${projectName}/src/network/routes/docs.ts`
586
+ },
587
+ home: {
588
+ content: `import { FastifyInstance } from 'fastify'
589
+ import { response } from 'network/response'
590
+
591
+ const Home = (app: FastifyInstance, prefix = '/'): void => {
592
+ app.get(\`\${prefix}\`, (request, reply) => {
593
+ response({
594
+ error: false,
595
+ message: 'Welcome to your Fastify Backend!',
596
+ reply,
597
+ status: 200
598
+ })
599
+ })
600
+ }
601
+
602
+ export { Home }
603
+ `,
604
+ file: `${projectName}/src/network/routes/home.ts`
605
+ },
606
+ index: {
607
+ content: `export * from './home'
608
+ export * from './user'
609
+ export * from './docs'
610
+ `,
611
+ file: `${projectName}/src/network/routes/index.ts`
612
+ },
613
+ user: {
614
+ content: `import { FastifyInstance } from 'fastify'
615
+ import { Type } from '@sinclair/typebox'
616
+
617
+ import { response } from 'network/response'
618
+ import {
619
+ userDto,
620
+ idSchema,
621
+ IdSchema,
622
+ storeUserSchema,
623
+ StoreUser
624
+ } from 'schemas'
625
+ import { UserService } from 'services'
626
+
627
+ const User = (app: FastifyInstance, prefix = '/api'): void => {
628
+ app
629
+ .post<{ Body: StoreUser }>(
630
+ \`\${prefix}/users\`,
631
+ {
632
+ schema: {
633
+ body: storeUserSchema,
634
+ response: {
635
+ 200: {
636
+ error: {
637
+ type: 'boolean'
638
+ },
639
+ message: userDto
640
+ }
641
+ },
642
+ tags: ['user']
643
+ }
644
+ },
645
+ async (request, reply) => {
646
+ const {
647
+ body: {
648
+ args: { lastName, name }
649
+ }
650
+ } = request
651
+ const us = new UserService({
652
+ userDtoWithoutId: { lastName, name }
653
+ })
654
+ const user = await us.process({ type: 'store' })
655
+
656
+ response({
657
+ error: false,
658
+ message: user,
659
+ reply,
660
+ status: 201
661
+ })
662
+ }
663
+ )
664
+ .get(
665
+ \`\${prefix}/users\`,
666
+ {
667
+ schema: {
668
+ response: {
669
+ 200: {
670
+ error: {
671
+ type: 'boolean'
672
+ },
673
+ message: Type.Array(userDto)
674
+ }
675
+ },
676
+ tags: ['user']
677
+ }
678
+ },
679
+ async (request, reply) => {
680
+ const us = new UserService()
681
+ const users = await us.process({ type: 'getAll' })
682
+
683
+ response({
684
+ error: false,
685
+ message: users,
686
+ reply,
687
+ status: 200
688
+ })
689
+ }
690
+ )
691
+ .delete(
692
+ \`\${prefix}/users\`,
693
+ {
694
+ schema: {
695
+ response: {
696
+ 200: {
697
+ error: {
698
+ type: 'boolean'
699
+ },
700
+ message: {
701
+ type: 'string'
702
+ }
703
+ }
704
+ },
705
+ tags: ['user']
706
+ }
707
+ },
708
+ async (request, reply) => {
709
+ const us = new UserService()
710
+ const result = await us.process({ type: 'deleteAll' })
711
+
712
+ response({
713
+ error: false,
714
+ message: result,
715
+ reply,
716
+ status: 200
717
+ })
718
+ }
719
+ )
720
+ .get<{ Params: IdSchema }>(
721
+ \`\${prefix}/user/:id\`,
722
+ {
723
+ schema: {
724
+ params: idSchema,
725
+ response: {
726
+ 200: {
727
+ error: {
728
+ type: 'boolean'
729
+ },
730
+ message: userDto
731
+ }
732
+ },
733
+ tags: ['user']
734
+ }
735
+ },
736
+ async (request, reply) => {
737
+ const {
738
+ params: { id }
739
+ } = request
740
+ const us = new UserService({ id })
741
+ const user = await us.process({ type: 'getOne' })
742
+
743
+ response({
744
+ error: false,
745
+ message: user,
746
+ reply,
747
+ status: 200
748
+ })
749
+ }
750
+ )
751
+ .patch<{ Body: StoreUser; Params: IdSchema }>(
752
+ \`\${prefix}/user/:id\`,
753
+ {
754
+ schema: {
755
+ body: storeUserSchema,
756
+ params: idSchema,
757
+ response: {
758
+ 200: {
759
+ error: {
760
+ type: 'boolean'
761
+ },
762
+ message: userDto
763
+ }
764
+ },
765
+ tags: ['user']
766
+ }
767
+ },
768
+ async (request, reply) => {
769
+ const {
770
+ body: {
771
+ args: { name, lastName }
772
+ },
773
+ params: { id }
774
+ } = request
775
+ const us = new UserService({
776
+ userDto: { name, lastName, id }
777
+ })
778
+ const user = await us.process({ type: 'update' })
779
+
780
+ response({
781
+ error: false,
782
+ message: user,
783
+ reply,
784
+ status: 200
785
+ })
786
+ }
787
+ )
788
+ .delete<{ Params: IdSchema }>(
789
+ \`\${prefix}/user/:id\`,
790
+ {
791
+ schema: {
792
+ params: idSchema,
793
+ response: {
794
+ 200: {
795
+ error: {
796
+ type: 'boolean'
797
+ },
798
+ message: {
799
+ type: 'string'
800
+ }
801
+ }
802
+ },
803
+ tags: ['user']
804
+ }
805
+ },
806
+ async (request, reply) => {
807
+ const {
808
+ params: { id }
809
+ } = request
810
+ const us = new UserService({ id })
811
+ const result = await us.process({ type: 'delete' })
812
+
813
+ response({
814
+ error: false,
815
+ message: result,
816
+ reply,
817
+ status: 200
818
+ })
819
+ }
820
+ )
821
+ }
822
+
823
+ export { User }
824
+ `,
825
+ file: `${projectName}/src/network/routes/user.ts`
826
+ }
827
+ },
828
+ utils: {
829
+ index: {
830
+ content: `/* eslint-disable @typescript-eslint/no-explicit-any */
831
+ import {
832
+ FastifyRouteSchemaDef,
833
+ FastifyValidationResult
834
+ } from 'fastify/types/schema'
835
+ import httpErrors from 'http-errors'
836
+ import Ajv from 'ajv'
837
+
838
+ const ajv = new Ajv({
839
+ removeAdditional: true,
840
+ useDefaults: true,
841
+ coerceTypes: true,
842
+ nullable: true
843
+ })
844
+
845
+ const validatorCompiler = ({
846
+ schema
847
+ }: FastifyRouteSchemaDef<any>): FastifyValidationResult => {
848
+ const validate = ajv.compile(schema)
849
+
850
+ return (data: unknown): boolean => {
851
+ const ok = validate(data)
852
+
853
+ if (!ok && validate.errors) {
854
+ const [error] = validate.errors
855
+ const errorMessage = \`\${error.dataPath.replace('.', '')} \${error.message}\`
856
+
857
+ throw new httpErrors.UnprocessableEntity(errorMessage)
858
+ }
859
+
860
+ return true
861
+ }
862
+ }
863
+
864
+ export { validatorCompiler }
865
+ `,
866
+ file: `${projectName}/src/network/utils/index.ts`
867
+ }
868
+ }
869
+ }
870
+
871
+ await writeFile(network.response.file, network.response.content)
872
+ await writeFile(network.router.file, network.router.content)
873
+ await writeFile(network.server.file, network.server.content)
874
+ await writeFile(network.routes.docs.file, network.routes.docs.content)
875
+ await writeFile(network.routes.home.file, network.routes.home.content)
876
+ await writeFile(network.routes.index.file, network.routes.index.content)
877
+ await writeFile(network.routes.user.file, network.routes.user.content)
878
+ await writeFile(network.utils.index.file, network.utils.index.content)
879
+ }
880
+ /**
881
+ * @param {Object} args
882
+ * @param {Boolean} args.fastify
883
+ * @param {String} args.projectName
884
+ */
885
+ module.exports = async ({ fastify, projectName }) => {
886
+ const createFoldersCommand = `mkdir ${projectName}/src/network \
887
+ ${projectName}/src/network/routes`
888
+
889
+ if (platform() === 'win32')
890
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
891
+ else await exec(createFoldersCommand)
892
+
893
+ const network = {
894
+ index: {
895
+ content: `export * from './routes'
896
+ export * from './server'
897
+ `,
898
+ file: `${projectName}/src/network/index.ts`
899
+ }
900
+ }
901
+
902
+ await writeFile(network.index.file, network.index.content)
903
+
904
+ if (fastify) await fastifyRestNetwork({ projectName })
905
+ else await expressRestNetwork({ projectName })
906
+ }