@anthonylzq/simba.js 4.3.1 → 5.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
@@ -1,4 +1,7 @@
1
- # Simba.js
1
+ <h1 align="center">
2
+ <!-- <p align="center">Simba.js</p> -->
3
+ <a href="https://simbajs.notion.site/783092dc7d444067b4c56a25d671f658?v=31060f3d17524ca58870e86c2960a6df"><img src="https://i.ibb.co/QHxn7kP/Gatonowww.png" alt="Simba.js"></a>
4
+ </h1>
2
5
 
3
6
  [![NPM version](https://img.shields.io/npm/v/@anthonylzq/simba.js.svg?style=flat)](https://www.npmjs.com/package/@anthonylzq/simba.js)
4
7
  [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/AnthonyLzq/simba.js/blob/master/LICENSE)
@@ -34,6 +37,7 @@ By doing this your prompt will ask you the following questions:
34
37
  - `Project version (0.1.0):` the initial version of the project, `0.1.0` as default.
35
38
  - `Select your license [1...7]:`, the license you have chosen for the project.
36
39
  - `License year (current year):`, the year where your license starts, current year as default.
40
+ - `Will this project use GraphQL? [y/n]:`, yes or no question, only **y** or **n** is accepted. This is not case sensitive.
37
41
  - `Will this project be deployed with Heroku? [y/n]:`, yes or no question, only **y** or **n** is accepted. This is not case sensitive.
38
42
 
39
43
  The second option you have is by passing flags in one single command. If you need help, please run:
@@ -69,6 +73,8 @@ Options:
69
73
  [boolean] [default: false]
70
74
  -F, --fastify Whether or not you want to use Fastify for your
71
75
  project [boolean] [default: false]
76
+ -g, --graphql Whether or not you want to use GraphQL for your
77
+ project [boolean] [default: false]
72
78
  -h, --help Show help [boolean]
73
79
 
74
80
  Examples:
@@ -94,18 +100,28 @@ As default, `yarn` is selected as package manager, but if you don't want to use
94
100
  simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -n
95
101
  ```
96
102
 
97
- And what if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
103
+ What if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
98
104
 
99
105
  ```bash
100
106
  simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F
101
107
  ```
102
108
 
109
+ And how can I use GraphQL? Well, you only have to pass the `-g` flag:
110
+
111
+ ```bash
112
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F -g
113
+ ```
114
+
103
115
  Finally, you may not want to use a license or one of the available licenses, don't worry, just don't pass the flag `-l` neither `--license` as follows:
104
116
 
105
117
  ```bash
106
118
  simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
107
119
  ```
108
120
 
121
+ #### Why didn't you use [`TypeGraphQL`](https://typegraphql.com/)?
122
+
123
+ [They don't support GraphQL v16.x.x](https://github.com/MichalLytek/type-graphql/issues/1100), until then.
124
+
109
125
  ## <a name="project-structure"></a>Project structure
110
126
 
111
127
  Regardless of the option chosen, a new folder will be generated with the name of the project, it will contain the following structure, depending if you have chosen Express or Fastify:
@@ -119,8 +135,6 @@ Regardless of the option chosen, a new folder will be generated with the name of
119
135
  ┃ ┣ 📂custom
120
136
  ┃ ┃ ┣ 📜request.d.ts
121
137
  ┃ ┃ ┗ 📜response.d.ts
122
- ┃ ┣ 📂dto
123
- ┃ ┃ ┗ 📜user.d.ts
124
138
  ┃ ┣ 📂models
125
139
  ┃ ┃ ┗ 📜user.d.ts
126
140
  ┃ ┗ 📜index.d.ts
@@ -137,7 +151,7 @@ Regardless of the option chosen, a new folder will be generated with the name of
137
151
  ┣ 📂network
138
152
  ┃ ┣ 📂routes
139
153
  ┃ ┃ ┣ 📂utils
140
- ┃ ┃ ┃ ┗ 📜docs.ts
154
+ ┃ ┃ ┃ ┗ 📜index.ts
141
155
  ┃ ┃ ┣ 📜home.ts
142
156
  ┃ ┃ ┣ 📜index.ts
143
157
  ┃ ┃ ┗ 📜user.ts
@@ -179,6 +193,81 @@ Regardless of the option chosen, a new folder will be generated with the name of
179
193
  📜yarn.lock (or package-lock.json)
180
194
  ```
181
195
 
196
+ ### Express-GraphQL case
197
+
198
+ ```
199
+ 📂node_modules
200
+ 📂src
201
+ ┣ 📂@types
202
+ ┃ ┣ 📂custom
203
+ ┃ ┃ ┣ 📜request.d.ts
204
+ ┃ ┃ ┗ 📜response.d.ts
205
+ ┃ ┣ 📂graphQL
206
+ ┃ ┃ ┗ 📜context.d.ts
207
+ ┃ ┣ 📂models
208
+ ┃ ┃ ┗ 📜user.d.ts
209
+ ┃ ┗ 📜index.d.ts
210
+ ┣ 📂database
211
+ ┃ ┣ 📂mongo
212
+ ┃ ┃ ┣ 📂models
213
+ ┃ ┃ ┃ ┣ 📜index.ts
214
+ ┃ ┃ ┃ ┗ 📜user.ts
215
+ ┃ ┃ ┣ 📂queries
216
+ ┃ ┃ ┃ ┣ 📜index.ts
217
+ ┃ ┃ ┃ ┗ 📜user.ts
218
+ ┃ ┃ ┗ 📜index.ts
219
+ ┃ ┗ 📜index.ts
220
+ ┣ 📂graphQL
221
+ ┃ ┣ 📂models
222
+ ┃ ┃ ┣ 📂User
223
+ ┃ ┃ ┃ ┣ 📜index.ts
224
+ ┃ ┃ ┃ ┣ 📜mutations.ts
225
+ ┃ ┃ ┃ ┣ 📜mutationsResolver.ts
226
+ ┃ ┃ ┃ ┣ 📜queries.ts
227
+ ┃ ┃ ┃ ┣ 📜queriesResolver.ts
228
+ ┃ ┃ ┃ ┣ 📜schemas.ts
229
+ ┃ ┃ ┃ ┗ 📜typeDefs.ts
230
+ ┃ ┃ ┣ 📂utils
231
+ ┃ ┃ ┃ ┣ 📂messages
232
+ ┃ ┃ ┃ ┃ ┣ 📜index.ts
233
+ ┃ ┃ ┃ ┃ ┗ 📜user.ts
234
+ ┃ ┃ ┃ ┗ 📜index.ts
235
+ ┃ ┃ ┗ 📜index.ts
236
+ ┃ ┗ 📜index.ts
237
+ ┣ 📂network
238
+ ┃ ┣ 📂routes
239
+ ┃ ┃ ┣ 📂utils
240
+ ┃ ┃ ┃ ┗ 📜index.ts
241
+ ┃ ┃ ┣ 📜home.ts
242
+ ┃ ┃ ┣ 📜index.ts
243
+ ┃ ┣ 📜index.ts
244
+ ┃ ┣ 📜response.ts
245
+ ┃ ┣ 📜routes.ts
246
+ ┃ ┗ 📜server.ts
247
+ ┣ 📂schemas
248
+ ┃ ┣ 📜index.ts
249
+ ┃ ┗ 📜user.ts
250
+ ┣ 📂utils
251
+ ┃ ┣ 📜docs.json
252
+ ┃ ┗ 📜index.ts
253
+ ┗ 📜index.ts
254
+ 📜.env
255
+ 📜.eslintignore
256
+ 📜.eslintrc
257
+ 📜.gitignore
258
+ 📜CHANGELOG.md
259
+ 📜Dockerfile
260
+ 📜heroku.yml
261
+ 📜LICENSE
262
+ 📜nodemon.json
263
+ 📜package.json
264
+ 📜README.md
265
+ 📜tsconfig.base.json
266
+ 📜tsconfig.json
267
+ 📜webpack.config.js
268
+ 📜yarn.lock (or package-lock.json)
269
+ ```
270
+
182
271
  ### Fastify case
183
272
 
184
273
  ```
@@ -241,12 +330,82 @@ Regardless of the option chosen, a new folder will be generated with the name of
241
330
  📜yarn.lock (or package-lock.json)
242
331
  ```
243
332
 
333
+ ### Fastify-GraphQL case
334
+
335
+ ```
336
+ 📂node_modules
337
+ 📂src
338
+ ┣ 📂@types
339
+ ┃ ┣ 📂graphQL
340
+ ┃ ┃ ┗ 📜context.d.ts
341
+ ┃ ┣ 📂dto
342
+ ┃ ┃ ┗ 📜user.d.ts
343
+ ┃ ┣ 📂models
344
+ ┃ ┃ ┗ 📜user.d.ts
345
+ ┃ ┗ 📜index.d.ts
346
+ ┣ 📂database
347
+ ┃ ┣ 📂mongo
348
+ ┃ ┃ ┣ 📂models
349
+ ┃ ┃ ┃ ┣ 📜index.ts
350
+ ┃ ┃ ┃ ┗ 📜user.ts
351
+ ┃ ┃ ┣ 📂queries
352
+ ┃ ┃ ┃ ┣ 📜index.ts
353
+ ┃ ┃ ┃ ┗ 📜user.ts
354
+ ┃ ┃ ┗ 📜index.ts
355
+ ┃ ┗ 📜index.ts
356
+ ┣ 📂graphQL
357
+ ┃ ┣ 📂models
358
+ ┃ ┃ ┣ 📂User
359
+ ┃ ┃ ┃ ┣ 📜index.ts
360
+ ┃ ┃ ┃ ┣ 📜mutations.ts
361
+ ┃ ┃ ┃ ┣ 📜mutationsResolver.ts
362
+ ┃ ┃ ┃ ┣ 📜queries.ts
363
+ ┃ ┃ ┃ ┣ 📜queriesResolver.ts
364
+ ┃ ┃ ┃ ┣ 📜schemas.ts
365
+ ┃ ┃ ┃ ┗ 📜typeDefs.ts
366
+ ┃ ┃ ┣ 📂utils
367
+ ┃ ┃ ┃ ┣ 📂messages
368
+ ┃ ┃ ┃ ┃ ┣ 📜index.ts
369
+ ┃ ┃ ┃ ┃ ┗ 📜user.ts
370
+ ┃ ┃ ┃ ┗ 📜index.ts
371
+ ┃ ┃ ┗ 📜index.ts
372
+ ┃ ┗ 📜index.ts
373
+ ┣ 📂network
374
+ ┃ ┣ 📂routes
375
+ ┃ ┃ ┣ 📜docs.ts
376
+ ┃ ┃ ┣ 📜home.ts
377
+ ┃ ┃ ┣ 📜index.ts
378
+ ┃ ┣ 📜index.ts
379
+ ┃ ┣ 📜response.ts
380
+ ┃ ┣ 📜routes.ts
381
+ ┃ ┗ 📜server.ts
382
+ ┣ 📂schemas
383
+ ┃ ┣ 📜index.ts
384
+ ┃ ┗ 📜user.ts
385
+ ┗ 📜index.ts
386
+ 📜.env
387
+ 📜.eslintignore
388
+ 📜.eslintrc
389
+ 📜.gitignore
390
+ 📜CHANGELOG.md
391
+ 📜Dockerfile
392
+ 📜heroku.yml
393
+ 📜LICENSE
394
+ 📜nodemon.json
395
+ 📜package.json
396
+ 📜README.md
397
+ 📜tsconfig.base.json
398
+ 📜tsconfig.json
399
+ 📜webpack.config.js
400
+ 📜yarn.lock (or package-lock.json)
401
+ ```
402
+
244
403
  If you want to check the content of the files, please check the [example](https://github.com/AnthonyLzq/simba.js/tree/master/example) folder, there you will an example for both, Express and Fastify.
245
404
 
246
405
  ### Some considerations
247
406
 
248
- - This project was based in other project from my own, [`typescript-project-generator`](https://www.npmjs.com/package/typescript-project-generator), but only considering the `express-mongoose` part.
249
- - You are able to run a server that has one main route, `home` (`/`), `user` (`api/user` or `api/user/:id`) and `docs` (`api/docs`).
407
+ - You are able to run a server that has one main route, `home` (`/`), `user` (`api/user` or `api/user/:id`) and `docs` (`api/docs`), in case you are not using GraphQL.
408
+ - In case you are using GraphQL, there are 4 mutations (`storeUser`, `updateUser`, `deleteAllUsers` and `deleteUser`) and 2 queries available (`getUsers` and `getUser`), you can find them in the playground under the route `/api`.
250
409
  - To connect your server with your `MongoDB` database, you need to provide your `uri` in the `.env`. By default, Simba will try to connect to a local database. The content of the `.env` file is:
251
410
 
252
411
  ```bash
@@ -288,16 +447,24 @@ If you want to check the content of the files, please check the [example](https:
288
447
 
289
448
  Please check the [`changelog.md`](https://github.com/AnthonyLzq/simba.js/blob/master/CHANGELOG.md) file. Also, if you want to check what is coming, check the [road map](https://simbajs.notion.site/simbajs/783092dc7d444067b4c56a25d671f658?v=31060f3d17524ca58870e86c2960a6df).
290
449
 
291
- ### Version 4.x.x
450
+ ### Version 5.x.x
292
451
 
293
452
  In this major version I would be focusing on adding new possible configurations according to the road map. The major changes of this version will be described here:
294
453
 
295
- - Replaced [`joi`](https://www.npmjs.com/package/joi) in favor of [`ajv`](https://www.npmjs.com/package/ajv) + [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox) in the Express case. [Why did I do this?](https://simbajs.notion.site/TypeBox-support-for-Express-f4e3cf8dd06f4c7ba4d8e4051a52688c)
296
- - Using more descriptive nouns, now every database object is represented with a DBO at the end, like: _UserDBO_. Also the objects that are sent and received will have a DTO at the end, like: _UserDTO_.
454
+ - API creation logic was split to improve scalability.
455
+ - Added support for GraphQL in both, Express and Fastify.
297
456
 
298
457
  ## <a name="notes"></a>Notes
299
458
 
300
- Here is the list of the packages that are being installed, as `devDependencies`:
459
+ Here is the list of the packages that are being installed, as `dependencies`:
460
+
461
+ - [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox)
462
+ - [`ajv`](https://www.npmjs.com/package/ajv)
463
+ - [`http-errors`](https://www.npmjs.com/package/http-errors)
464
+ - [`mongoose`](https://mongoosejs.com/)
465
+ - [`pino-pretty`](https://www.npmjs.com/package/pino-pretty)
466
+
467
+ As `devDependencies`:
301
468
 
302
469
  - [`@types/http-errors`](https://www.npmjs.com/package/@types/http-errors)
303
470
  - [`@types/node`](https://www.npmjs.com/package/@types/node)
@@ -321,28 +488,35 @@ Here is the list of the packages that are being installed, as `devDependencies`:
321
488
  - [`webpack-cli`](https://www.npmjs.com/package/webpack-cli)
322
489
  - [`webpack-node-externals`](https://www.npmjs.com/package/webpack-node-externals)
323
490
 
324
- As `dependencies`:
491
+ ### In case you are using GraphQL
325
492
 
326
- - [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox)
493
+ As `dependencies`:
494
+ - [`@graphql-tools/schema`](https://www.npmjs.com/package/@graphql-tools/schema)
327
495
  - [`ajv`](https://www.npmjs.com/package/ajv)
328
- - [`http-errors`](https://www.npmjs.com/package/http-errors)
329
- - [`mongoose`](https://mongoosejs.com/)
496
+ - [`ajv-formats`](https://www.npmjs.com/package/ajv-formats)
497
+ - [`apollo-server-core`](https://www.npmjs.com/package/apollo-server-core)
498
+ - [`graphql`](https://www.npmjs.com/package/graphql)
330
499
 
331
500
  ### Express case
332
501
 
502
+ As `dependencies`:
503
+
504
+ - [`cors`](https://www.npmjs.com/package/cors)
505
+ - [`express`](https://www.npmjs.com/package/express)
506
+ - [`express-pino-logger`](https://www.npmjs.com/package/express-pino-logger)
507
+ - [`swagger-ui-express`](https://www.npmjs.com/package/swagger-ui-express)
508
+
333
509
  As `devDependencies`:
334
510
 
335
511
  - [`@types/express`](https://www.npmjs.com/package/@types/express)
336
512
  - [`@types/cors`](https://www.npmjs.com/package/@types/cors)
337
- - [`@types/morgan`](https://www.npmjs.com/package/@types/morgan)
513
+ - [`@types/express-pino-logger`](https://www.npmjs.com/package/@types/express-pino-logger)
338
514
  - [`@types/swagger-ui-express`](https://www.npmjs.com/package/@types/swagger-ui-express)
339
515
 
340
- As `dependencies`:
516
+ #### In case you are using GraphQL
341
517
 
342
- - [`cors`](https://www.npmjs.com/package/cors)
343
- - [`express`](https://www.npmjs.com/package/express)
344
- - [`morgan`](https://www.npmjs.com/package/morgan)
345
- - [`swagger-ui-express`](https://www.npmjs.com/package/swagger-ui-express)
518
+ As `dependencies`:
519
+ - [`apollo-server-express`](https://www.npmjs.com/package/apollo-server-express)
346
520
 
347
521
  ### Fastify case
348
522
 
@@ -352,6 +526,12 @@ As `dependencies`:
352
526
  - [`fastify-cors`](https://www.npmjs.com/package/fastify-cors)
353
527
  - [`fastify-swagger`](https://www.npmjs.com/package/fastify-swagger)
354
528
 
529
+ #### In case you are using GraphQL
530
+
531
+ As `dependencies`:
532
+ - [`apollo-server-fastify`](https://www.npmjs.com/package/apollo-server-fastify)
533
+ - [`apollo-server-plugin-base`](https://www.npmjs.com/package/apollo-server-plugin-base)
534
+
355
535
  Feel free to contribute to this project. Every contribution will be appreciated.
356
536
 
357
537
  ## Author
package/lib/index.js CHANGED
@@ -52,6 +52,8 @@ const argv = yargs(hideBin(process.argv))
52
52
  )
53
53
  .alias('F', 'fastify')
54
54
  .describe('F', 'Whether or not you want to use Fastify for your project')
55
+ .alias('g', 'graphql')
56
+ .describe('g', 'Whether or not you want to use GraphQL for your project')
55
57
  .default({
56
58
  H: false,
57
59
  n: false,
@@ -60,9 +62,10 @@ const argv = yargs(hideBin(process.argv))
60
62
  v: '0.1.0',
61
63
  f: 'src/index.ts',
62
64
  q: false,
63
- F: false
65
+ F: false,
66
+ g: false
64
67
  })
65
- .boolean(['H', 'n', 'q', 'F'])
68
+ .boolean(['H', 'n', 'q', 'F', 'g'])
66
69
  .help('h')
67
70
  .alias('h', 'help')
68
71
  .epilog('Developed by AnthonyLzq').argv
@@ -80,7 +83,8 @@ const config = {
80
83
  npm: false,
81
84
  manager: 'yarn add',
82
85
  mainFile: 'src/index.ts',
83
- fastify: false
86
+ fastify: false,
87
+ graphql: false
84
88
  }
85
89
  const UNLICENSED = 'unlicensed'
86
90
  const LICENSES = [
@@ -132,7 +136,6 @@ const main = async () => {
132
136
  prompt: '> Express or Fastify? '
133
137
  }
134
138
  )
135
-
136
139
  readLineSync.promptLoop(
137
140
  input => {
138
141
  config.projectName = input.toLowerCase()
@@ -145,7 +148,6 @@ const main = async () => {
145
148
  prompt: '> Project name: '
146
149
  }
147
150
  )
148
-
149
151
  readLineSync.promptLoop(
150
152
  input => {
151
153
  config.projectDescription = input
@@ -158,7 +160,6 @@ const main = async () => {
158
160
  prompt: '> Project description: '
159
161
  }
160
162
  )
161
-
162
163
  readLineSync.promptLoop(
163
164
  input => {
164
165
  config.author = input
@@ -171,12 +172,10 @@ const main = async () => {
171
172
  prompt: '> Author: '
172
173
  }
173
174
  )
174
-
175
175
  config.email = readLineSync.questionEMail('> Email: ', {
176
176
  limit: EMAIL_REGEXP,
177
177
  limitMessage: 'That is not a valid email!'
178
178
  })
179
-
180
179
  config.version = readLineSync.question('> Project version (0.1.0): ')
181
180
  config.version = config.version === '' ? '0.1.0' : config.version
182
181
 
@@ -192,7 +191,6 @@ const main = async () => {
192
191
  .toLowerCase()
193
192
  .replace(/ /g, '-')
194
193
  .replace('d', '')
195
-
196
194
  readLineSync.promptLoop(
197
195
  input => {
198
196
  if (input !== '') config.licenseYear = input
@@ -205,14 +203,18 @@ const main = async () => {
205
203
  prompt: `> License year (${config.licenseYear}): `
206
204
  }
207
205
  )
208
-
206
+ config.graphql = readLineSync.keyInYNStrict(
207
+ '> Will this project use GraphQL? ',
208
+ {
209
+ caseSensitive: false
210
+ }
211
+ )
209
212
  config.heroku = readLineSync.keyInYNStrict(
210
213
  '> Will this project be deployed with Heroku? ',
211
214
  {
212
215
  caseSensitive: false
213
216
  }
214
217
  )
215
-
216
218
  config.mainFile = readLineSync.question('> Main file (src/index.ts): ')
217
219
  } else {
218
220
  if (!argv.author) return console.log('Error! An author is required!')
@@ -283,6 +285,8 @@ const main = async () => {
283
285
  config.manager = 'npm i'
284
286
  }
285
287
 
288
+ if (argv.graphql) config.graphql = true
289
+
286
290
  if (!argv.mainFile) console.log('Using src/index.ts as default main file')
287
291
  else config.mainFile = argv.mainFile
288
292
  }
@@ -305,4 +309,6 @@ module.exports = main
305
309
  * @property {Boolean} npm true means that the package manager will be npm, otherwise yarn
306
310
  * @property {'yarn add'|'npm i'} manager command that will be used to install packages
307
311
  * @property {String} mainFile main file of the project
312
+ * @property {Boolean} fastify true means that the project will be using Fastify
313
+ * @property {Boolean} graphql true means that the project will be using GraphQL
308
314
  */
@@ -0,0 +1,177 @@
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} projectName
9
+ */
10
+ const mongoF = async ({ projectName }) => {
11
+ const createFoldersCommand = `mkdir ${projectName}/src/database/mongo \
12
+ ${projectName}/src/database/mongo/models \
13
+ ${projectName}/src/database/mongo/queries`
14
+
15
+ if (platform() === 'win32')
16
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
17
+ else await exec(createFoldersCommand)
18
+
19
+ const database = {
20
+ index: {
21
+ content: "export * from './mongo'\n",
22
+ file: `${projectName}/src/database/index.ts`
23
+ },
24
+ mongo: {
25
+ index: {
26
+ content: `export * from './models'
27
+ export * from './queries'
28
+ `,
29
+ file: `${projectName}/src/database/mongo/index.ts`
30
+ },
31
+ models: {
32
+ index: {
33
+ content: "export * from './user'\n",
34
+ file: `${projectName}/src/database/mongo/models/index.ts`
35
+ },
36
+ user: {
37
+ content: `import { model, Schema } from 'mongoose'
38
+
39
+ const UserSchema = new Schema<UserDBO>(
40
+ {
41
+ lastName: {
42
+ required: true,
43
+ type: String
44
+ },
45
+ name: {
46
+ required: true,
47
+ type: String
48
+ }
49
+ },
50
+ {
51
+ timestamps: true,
52
+ versionKey: false,
53
+ toObject: {
54
+ transform: (_, ret) => {
55
+ ret.id = ret._id.toString()
56
+ delete ret._id
57
+ }
58
+ }
59
+ }
60
+ )
61
+
62
+ const UserModel = model<UserDBO>('users', UserSchema)
63
+
64
+ export { UserModel }
65
+ `,
66
+ file: `${projectName}/src/database/mongo/models/user.ts`
67
+ }
68
+ },
69
+ queries: {
70
+ index: {
71
+ content: "export * from './user'\n",
72
+ file: `${projectName}/src/database/mongo/queries/index.ts`
73
+ },
74
+ user: {
75
+ content: `import { Document, Types } from 'mongoose'
76
+
77
+ import { UserModel } from '..'
78
+ import { UserDTO } from 'schemas'
79
+
80
+ const userDBOtoDTO = (
81
+ userDBO: Document<unknown, unknown, UserDBO> &
82
+ UserDBO & {
83
+ _id: Types.ObjectId
84
+ }
85
+ ): UserDTO => ({
86
+ ...userDBO.toObject(),
87
+ createdAt: userDBO.createdAt.toISOString(),
88
+ updatedAt: userDBO.updatedAt.toISOString()
89
+ })
90
+
91
+ const store = async (userData: UserDTO): Promise<UserDTO> => {
92
+ const user = new UserModel(userData)
93
+
94
+ await user.save()
95
+
96
+ return userDBOtoDTO(user)
97
+ }
98
+
99
+ const remove = async (
100
+ id: string | null = null
101
+ ): Promise<UserDTO | number | null> => {
102
+ if (id) {
103
+ const removedUser = await UserModel.findByIdAndRemove(id)
104
+
105
+ if (!removedUser) return null
106
+
107
+ return userDBOtoDTO(removedUser)
108
+ }
109
+
110
+ return (await UserModel.deleteMany({})).deletedCount
111
+ }
112
+
113
+ const get = async (
114
+ id: string | null = null
115
+ ): Promise<UserDTO[] | UserDTO | null> => {
116
+ if (id) {
117
+ const user = await UserModel.findById(id)
118
+
119
+ return user ? userDBOtoDTO(user) : null
120
+ }
121
+
122
+ const users = await UserModel.find({})
123
+
124
+ return users.map(u => userDBOtoDTO(u))
125
+ }
126
+
127
+ const update = async (userData: UserDTO): Promise<UserDTO | null> => {
128
+ const { id, ...rest } = userData
129
+ const user = await UserModel.findByIdAndUpdate(id, rest, { new: true })
130
+
131
+ return user ? userDBOtoDTO(user) : null
132
+ }
133
+
134
+ export { store, remove, get, update }
135
+ `,
136
+ file: `${projectName}/src/database/mongo/queries/user.ts`
137
+ }
138
+ }
139
+ }
140
+ }
141
+
142
+ await Promise.all([
143
+ await writeFile(database.index.file, database.index.content),
144
+ await writeFile(database.mongo.index.file, database.mongo.index.content),
145
+ await writeFile(
146
+ database.mongo.models.index.file,
147
+ database.mongo.models.index.content
148
+ ),
149
+ await writeFile(
150
+ database.mongo.models.user.file,
151
+ database.mongo.models.user.content
152
+ ),
153
+ await writeFile(
154
+ database.mongo.queries.index.file,
155
+ database.mongo.queries.index.content
156
+ ),
157
+ await writeFile(
158
+ database.mongo.queries.user.file,
159
+ database.mongo.queries.user.content
160
+ )
161
+ ])
162
+ }
163
+
164
+ /**
165
+ * @param {Object} args
166
+ * @param {Boolean|undefined} args.mongo
167
+ * @param {String} args.projectName
168
+ */
169
+ module.exports = async ({ mongo = true, projectName }) => {
170
+ const createFoldersCommand = `mkdir ${projectName}/src/database`
171
+
172
+ if (platform() === 'win32')
173
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
174
+ else await exec(createFoldersCommand)
175
+
176
+ if (mongo) await mongoF({ projectName })
177
+ }