@anthonylzq/simba.js 4.3.0 → 5.0.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
@@ -34,6 +34,7 @@ By doing this your prompt will ask you the following questions:
34
34
  - `Project version (0.1.0):` the initial version of the project, `0.1.0` as default.
35
35
  - `Select your license [1...7]:`, the license you have chosen for the project.
36
36
  - `License year (current year):`, the year where your license starts, current year as default.
37
+ - `Will this project use GraphQL? [y/n]:`, yes or no question, only **y** or **n** is accepted. This is not case sensitive.
37
38
  - `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
39
 
39
40
  The second option you have is by passing flags in one single command. If you need help, please run:
@@ -69,6 +70,8 @@ Options:
69
70
  [boolean] [default: false]
70
71
  -F, --fastify Whether or not you want to use Fastify for your
71
72
  project [boolean] [default: false]
73
+ -g, --graphql Whether or not you want to use GraphQL for your
74
+ project [boolean] [default: false]
72
75
  -h, --help Show help [boolean]
73
76
 
74
77
  Examples:
@@ -94,18 +97,28 @@ As default, `yarn` is selected as package manager, but if you don't want to use
94
97
  simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -n
95
98
  ```
96
99
 
97
- And what if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
100
+ What if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
98
101
 
99
102
  ```bash
100
103
  simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F
101
104
  ```
102
105
 
106
+ And how can I use GraphQL? Well, you only have to pass the `-g` flag:
107
+
108
+ ```bash
109
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F -g
110
+ ```
111
+
103
112
  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
113
 
105
114
  ```bash
106
115
  simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
107
116
  ```
108
117
 
118
+ #### Why didn't you use [`TypeGraphQL`](https://typegraphql.com/)?
119
+
120
+ [They don't support GraphQL v16.x.x](https://github.com/MichalLytek/type-graphql/issues/1100), until then.
121
+
109
122
  ## <a name="project-structure"></a>Project structure
110
123
 
111
124
  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 +132,6 @@ Regardless of the option chosen, a new folder will be generated with the name of
119
132
  ┃ ┣ 📂custom
120
133
  ┃ ┃ ┣ 📜request.d.ts
121
134
  ┃ ┃ ┗ 📜response.d.ts
122
- ┃ ┣ 📂dto
123
- ┃ ┃ ┗ 📜user.d.ts
124
135
  ┃ ┣ 📂models
125
136
  ┃ ┃ ┗ 📜user.d.ts
126
137
  ┃ ┗ 📜index.d.ts
@@ -137,7 +148,7 @@ Regardless of the option chosen, a new folder will be generated with the name of
137
148
  ┣ 📂network
138
149
  ┃ ┣ 📂routes
139
150
  ┃ ┃ ┣ 📂utils
140
- ┃ ┃ ┃ ┗ 📜docs.ts
151
+ ┃ ┃ ┃ ┗ 📜index.ts
141
152
  ┃ ┃ ┣ 📜home.ts
142
153
  ┃ ┃ ┣ 📜index.ts
143
154
  ┃ ┃ ┗ 📜user.ts
@@ -179,6 +190,81 @@ Regardless of the option chosen, a new folder will be generated with the name of
179
190
  📜yarn.lock (or package-lock.json)
180
191
  ```
181
192
 
193
+ ### Express-GraphQL case
194
+
195
+ ```
196
+ 📂node_modules
197
+ 📂src
198
+ ┣ 📂@types
199
+ ┃ ┣ 📂custom
200
+ ┃ ┃ ┣ 📜request.d.ts
201
+ ┃ ┃ ┗ 📜response.d.ts
202
+ ┃ ┣ 📂graphQL
203
+ ┃ ┃ ┗ 📜context.d.ts
204
+ ┃ ┣ 📂models
205
+ ┃ ┃ ┗ 📜user.d.ts
206
+ ┃ ┗ 📜index.d.ts
207
+ ┣ 📂database
208
+ ┃ ┣ 📂mongo
209
+ ┃ ┃ ┣ 📂models
210
+ ┃ ┃ ┃ ┣ 📜index.ts
211
+ ┃ ┃ ┃ ┗ 📜user.ts
212
+ ┃ ┃ ┣ 📂queries
213
+ ┃ ┃ ┃ ┣ 📜index.ts
214
+ ┃ ┃ ┃ ┗ 📜user.ts
215
+ ┃ ┃ ┗ 📜index.ts
216
+ ┃ ┗ 📜index.ts
217
+ ┣ 📂graphQL
218
+ ┃ ┣ 📂models
219
+ ┃ ┃ ┣ 📂User
220
+ ┃ ┃ ┃ ┣ 📜index.ts
221
+ ┃ ┃ ┃ ┣ 📜mutations.ts
222
+ ┃ ┃ ┃ ┣ 📜mutationsResolver.ts
223
+ ┃ ┃ ┃ ┣ 📜queries.ts
224
+ ┃ ┃ ┃ ┣ 📜queriesResolver.ts
225
+ ┃ ┃ ┃ ┣ 📜schemas.ts
226
+ ┃ ┃ ┃ ┗ 📜typeDefs.ts
227
+ ┃ ┃ ┣ 📂utils
228
+ ┃ ┃ ┃ ┣ 📂messages
229
+ ┃ ┃ ┃ ┃ ┣ 📜index.ts
230
+ ┃ ┃ ┃ ┃ ┗ 📜user.ts
231
+ ┃ ┃ ┃ ┗ 📜index.ts
232
+ ┃ ┃ ┗ 📜index.ts
233
+ ┃ ┗ 📜index.ts
234
+ ┣ 📂network
235
+ ┃ ┣ 📂routes
236
+ ┃ ┃ ┣ 📂utils
237
+ ┃ ┃ ┃ ┗ 📜index.ts
238
+ ┃ ┃ ┣ 📜home.ts
239
+ ┃ ┃ ┣ 📜index.ts
240
+ ┃ ┣ 📜index.ts
241
+ ┃ ┣ 📜response.ts
242
+ ┃ ┣ 📜routes.ts
243
+ ┃ ┗ 📜server.ts
244
+ ┣ 📂schemas
245
+ ┃ ┣ 📜index.ts
246
+ ┃ ┗ 📜user.ts
247
+ ┣ 📂utils
248
+ ┃ ┣ 📜docs.json
249
+ ┃ ┗ 📜index.ts
250
+ ┗ 📜index.ts
251
+ 📜.env
252
+ 📜.eslintignore
253
+ 📜.eslintrc
254
+ 📜.gitignore
255
+ 📜CHANGELOG.md
256
+ 📜Dockerfile
257
+ 📜heroku.yml
258
+ 📜LICENSE
259
+ 📜nodemon.json
260
+ 📜package.json
261
+ 📜README.md
262
+ 📜tsconfig.base.json
263
+ 📜tsconfig.json
264
+ 📜webpack.config.js
265
+ 📜yarn.lock (or package-lock.json)
266
+ ```
267
+
182
268
  ### Fastify case
183
269
 
184
270
  ```
@@ -241,12 +327,82 @@ Regardless of the option chosen, a new folder will be generated with the name of
241
327
  📜yarn.lock (or package-lock.json)
242
328
  ```
243
329
 
330
+ ### Fastify-GraphQL case
331
+
332
+ ```
333
+ 📂node_modules
334
+ 📂src
335
+ ┣ 📂@types
336
+ ┃ ┣ 📂graphQL
337
+ ┃ ┃ ┗ 📜context.d.ts
338
+ ┃ ┣ 📂dto
339
+ ┃ ┃ ┗ 📜user.d.ts
340
+ ┃ ┣ 📂models
341
+ ┃ ┃ ┗ 📜user.d.ts
342
+ ┃ ┗ 📜index.d.ts
343
+ ┣ 📂database
344
+ ┃ ┣ 📂mongo
345
+ ┃ ┃ ┣ 📂models
346
+ ┃ ┃ ┃ ┣ 📜index.ts
347
+ ┃ ┃ ┃ ┗ 📜user.ts
348
+ ┃ ┃ ┣ 📂queries
349
+ ┃ ┃ ┃ ┣ 📜index.ts
350
+ ┃ ┃ ┃ ┗ 📜user.ts
351
+ ┃ ┃ ┗ 📜index.ts
352
+ ┃ ┗ 📜index.ts
353
+ ┣ 📂graphQL
354
+ ┃ ┣ 📂models
355
+ ┃ ┃ ┣ 📂User
356
+ ┃ ┃ ┃ ┣ 📜index.ts
357
+ ┃ ┃ ┃ ┣ 📜mutations.ts
358
+ ┃ ┃ ┃ ┣ 📜mutationsResolver.ts
359
+ ┃ ┃ ┃ ┣ 📜queries.ts
360
+ ┃ ┃ ┃ ┣ 📜queriesResolver.ts
361
+ ┃ ┃ ┃ ┣ 📜schemas.ts
362
+ ┃ ┃ ┃ ┗ 📜typeDefs.ts
363
+ ┃ ┃ ┣ 📂utils
364
+ ┃ ┃ ┃ ┣ 📂messages
365
+ ┃ ┃ ┃ ┃ ┣ 📜index.ts
366
+ ┃ ┃ ┃ ┃ ┗ 📜user.ts
367
+ ┃ ┃ ┃ ┗ 📜index.ts
368
+ ┃ ┃ ┗ 📜index.ts
369
+ ┃ ┗ 📜index.ts
370
+ ┣ 📂network
371
+ ┃ ┣ 📂routes
372
+ ┃ ┃ ┣ 📜docs.ts
373
+ ┃ ┃ ┣ 📜home.ts
374
+ ┃ ┃ ┣ 📜index.ts
375
+ ┃ ┣ 📜index.ts
376
+ ┃ ┣ 📜response.ts
377
+ ┃ ┣ 📜routes.ts
378
+ ┃ ┗ 📜server.ts
379
+ ┣ 📂schemas
380
+ ┃ ┣ 📜index.ts
381
+ ┃ ┗ 📜user.ts
382
+ ┗ 📜index.ts
383
+ 📜.env
384
+ 📜.eslintignore
385
+ 📜.eslintrc
386
+ 📜.gitignore
387
+ 📜CHANGELOG.md
388
+ 📜Dockerfile
389
+ 📜heroku.yml
390
+ 📜LICENSE
391
+ 📜nodemon.json
392
+ 📜package.json
393
+ 📜README.md
394
+ 📜tsconfig.base.json
395
+ 📜tsconfig.json
396
+ 📜webpack.config.js
397
+ 📜yarn.lock (or package-lock.json)
398
+ ```
399
+
244
400
  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
401
 
246
402
  ### Some considerations
247
403
 
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`).
404
+ - 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.
405
+ - 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
406
  - 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
407
 
252
408
  ```bash
@@ -288,16 +444,24 @@ If you want to check the content of the files, please check the [example](https:
288
444
 
289
445
  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
446
 
291
- ### Version 4.x.x
447
+ ### Version 5.x.x
292
448
 
293
449
  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
450
 
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_.
451
+ - API creation logic was split to improve scalability.
452
+ - Added support for GraphQL in both, Express and Fastify.
297
453
 
298
454
  ## <a name="notes"></a>Notes
299
455
 
300
- Here is the list of the packages that are being installed, as `devDependencies`:
456
+ Here is the list of the packages that are being installed, as `dependencies`:
457
+
458
+ - [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox)
459
+ - [`ajv`](https://www.npmjs.com/package/ajv)
460
+ - [`http-errors`](https://www.npmjs.com/package/http-errors)
461
+ - [`mongoose`](https://mongoosejs.com/)
462
+ - [`pino-pretty`](https://www.npmjs.com/package/pino-pretty)
463
+
464
+ As `devDependencies`:
301
465
 
302
466
  - [`@types/http-errors`](https://www.npmjs.com/package/@types/http-errors)
303
467
  - [`@types/node`](https://www.npmjs.com/package/@types/node)
@@ -321,28 +485,35 @@ Here is the list of the packages that are being installed, as `devDependencies`:
321
485
  - [`webpack-cli`](https://www.npmjs.com/package/webpack-cli)
322
486
  - [`webpack-node-externals`](https://www.npmjs.com/package/webpack-node-externals)
323
487
 
324
- As `dependencies`:
488
+ ### In case you are using GraphQL
325
489
 
326
- - [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox)
490
+ As `dependencies`:
491
+ - [`@graphql-tools/schema`](https://www.npmjs.com/package/@graphql-tools/schema)
327
492
  - [`ajv`](https://www.npmjs.com/package/ajv)
328
- - [`http-errors`](https://www.npmjs.com/package/http-errors)
329
- - [`mongoose`](https://mongoosejs.com/)
493
+ - [`ajv-formats`](https://www.npmjs.com/package/ajv-formats)
494
+ - [`apollo-server-core`](https://www.npmjs.com/package/apollo-server-core)
495
+ - [`graphql`](https://www.npmjs.com/package/graphql)
330
496
 
331
497
  ### Express case
332
498
 
499
+ As `dependencies`:
500
+
501
+ - [`cors`](https://www.npmjs.com/package/cors)
502
+ - [`express`](https://www.npmjs.com/package/express)
503
+ - [`express-pino-logger`](https://www.npmjs.com/package/express-pino-logger)
504
+ - [`swagger-ui-express`](https://www.npmjs.com/package/swagger-ui-express)
505
+
333
506
  As `devDependencies`:
334
507
 
335
508
  - [`@types/express`](https://www.npmjs.com/package/@types/express)
336
509
  - [`@types/cors`](https://www.npmjs.com/package/@types/cors)
337
- - [`@types/morgan`](https://www.npmjs.com/package/@types/morgan)
510
+ - [`@types/express-pino-logger`](https://www.npmjs.com/package/@types/express-pino-logger)
338
511
  - [`@types/swagger-ui-express`](https://www.npmjs.com/package/@types/swagger-ui-express)
339
512
 
340
- As `dependencies`:
513
+ #### In case you are using GraphQL
341
514
 
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)
515
+ As `dependencies`:
516
+ - [`apollo-server-express`](https://www.npmjs.com/package/apollo-server-express)
346
517
 
347
518
  ### Fastify case
348
519
 
@@ -352,6 +523,12 @@ As `dependencies`:
352
523
  - [`fastify-cors`](https://www.npmjs.com/package/fastify-cors)
353
524
  - [`fastify-swagger`](https://www.npmjs.com/package/fastify-swagger)
354
525
 
526
+ #### In case you are using GraphQL
527
+
528
+ As `dependencies`:
529
+ - [`apollo-server-fastify`](https://www.npmjs.com/package/apollo-server-fastify)
530
+ - [`apollo-server-plugin-base`](https://www.npmjs.com/package/apollo-server-plugin-base)
531
+
355
532
  Feel free to contribute to this project. Every contribution will be appreciated.
356
533
 
357
534
  ## 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
+ }