@anthonylzq/simba.js 2.1.1 → 3.2.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,24 +1,11 @@
1
1
  # Simba.js
2
2
 
3
+ [![NPM version](https://img.shields.io/npm/v/@anthonylzq/simba.js.svg?style=flat)](https://www.npmjs.com/package/@anthonylzq/simba.js)
4
+ [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/AnthonyLzq/simba.js/blob/master/LICENSE)
3
5
  [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
6
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
4
7
 
5
- Set up a modern backend app by running one command. This project has the goal to create a complete setup for a backend application using `TypeScript` and `Express`. It will create many files that are usually created manually. Currently the following files are being created:
6
-
7
- - `.env`
8
- - `.eslintignore`
9
- - `.eslintrc`
10
- - `.gitignore`
11
- - `CHANGELOG.md`
12
- - `Dockerfile`
13
- - `heroku.yml` (optional)
14
- - `LICENSE` (optional, `MIT` as example)
15
- - `nodemon.json`
16
- - `package.json`
17
- - `README.md`
18
- - `tsconfig.base.json`
19
- - `tsconfig.json`
20
- - `webpack.config.js`
21
- - `yarn.lock` (or `package-lock.json`)
8
+ Set up a modern backend app by running one command. This project has the goal to create a complete setup for a backend application using `TypeScript` and `Express` or `Fastify`. It will create many files that are usually created manually. Think about Simba.js like a [CRA](https://create-react-app.dev/), but for backend development. Check the [**project structure**](#project-structure) for more information.
22
9
 
23
10
  ## Installation
24
11
 
@@ -38,7 +25,8 @@ simba -q
38
25
 
39
26
  By doing this your prompt will ask you the following questions:
40
27
 
41
- - `Yarn or npm?`, only one of them is valid.
28
+ - `Yarn or npm?`, only one of them is valid (lowercase).
29
+ - `Express or Fastify?`, only one of them is valid (lowercase).
42
30
  - `Project name:`, at least one character must be provided.
43
31
  - `Project description:`, at least one character must be provided.
44
32
  - `Author:`, at least one character must be provided.
@@ -57,8 +45,8 @@ simba -h
57
45
  This will generate the following output:
58
46
 
59
47
  ```bash
60
- simba [options] (if you it installed globally) or only simba if you want to be
61
- asked for the options one by one
48
+ "simba [options]" (if you it installed globally) or only "simba -q" if you want
49
+ to be asked for the options one by one
62
50
 
63
51
  Options:
64
52
  -N, --projectName Project name
@@ -72,13 +60,15 @@ Options:
72
60
  3.0, in lowercase without its version
73
61
  [default: "unlicensed"]
74
62
  -v, --version Project initial version [default: "0.1.0"]
75
- -y, --licenseYear Year when the license starts [default: "2021"]
63
+ -y, --licenseYear Year when the license starts [default: "2022"]
76
64
  -n, --npm Whether or not the project should use npm as package
77
65
  manager [boolean] [default: false]
78
66
  -f, --mainFile Main file of the project [default: "src/index.ts"]
79
67
  -q, --questions Whether or not you want to be asked to answer the
80
68
  questions related to the project one by one
81
69
  [boolean] [default: false]
70
+ -F, --fastify Whether or not you want to use Fastify for your
71
+ project [boolean] [default: false]
82
72
  -h, --help Show help [boolean]
83
73
 
84
74
  Examples:
@@ -88,7 +78,39 @@ Examples:
88
78
  Developed by AnthonyLzq
89
79
  ```
90
80
 
91
- Regardless of the option chosen, a new folder will be generated with the name of the project, it will contain the following structure:
81
+ ### Examples
82
+
83
+ Let's suppose you want to build a project that will be deployed to Heroku, so should run:
84
+
85
+ ```bash
86
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H
87
+ ```
88
+
89
+ Here we are specifying that we want to create a new project called `myProject` using the `MIT` license, my name and my email are respectively: `myName` and `myEmail@email.com` and I want to use heroku to deploy this server.
90
+
91
+ As default, `yarn` is selected as package manager, but if you don't want to use it, you can pass the flag `-n` or `--npm` as follows:
92
+
93
+ ```bash
94
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -n
95
+ ```
96
+
97
+ And what if I want to use Fastify instead Express? Well, you only have to pass the `-F` flag:
98
+
99
+ ```bash
100
+ simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -F
101
+ ```
102
+
103
+ 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
+
105
+ ```bash
106
+ simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
107
+ ```
108
+
109
+ ## <a name="project-structure"></a>Project structure
110
+
111
+ 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:
112
+
113
+ ### Express case
92
114
 
93
115
  ```
94
116
  📂node_modules
@@ -143,6 +165,7 @@ Regardless of the option chosen, a new folder will be generated with the name of
143
165
  📜CHANGELOG.md
144
166
  📜Dockerfile
145
167
  📜heroku.yml
168
+ 📜index.http
146
169
  📜LICENSE
147
170
  📜nodemon.json
148
171
  📜package.json
@@ -154,27 +177,69 @@ Regardless of the option chosen, a new folder will be generated with the name of
154
177
  📜yarn.lock (or package-lock.json)
155
178
  ```
156
179
 
157
- ### Examples
158
-
159
- Let's suppose you want to build a project that will be deployed to Heroku, so should run:
180
+ ### Fastify case
160
181
 
161
- ```bash
162
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H
163
182
  ```
164
-
165
- Here we are specifying that we want to create a new project called `myProject` using the `MIT` license, my name and my email are respectively: `myName` and `myEmail@email.com` and I want to use heroku to deploy this server.
166
-
167
- As default, `yarn` is selected as package manager, but if you don't want to use it, you can pass the flag `-n` or `--npm` as follows:
168
-
169
- ```bash
170
- simba -N myProject -D 'This is a test' -l mit -a myName -e myEmail@email.com -H -n
183
+ 📂node_modules
184
+ 📂src
185
+ ┣ 📂@types
186
+ 📂dto
187
+ ┃ ┃ ┗ 📜user.d.ts
188
+ ┃ ┣ 📂models
189
+ 📜user.d.ts
190
+ ┃ ┗ 📜index.d.ts
191
+ ┣ 📂database
192
+ ┃ ┣ 📂mongo
193
+ ┃ ┃ ┣ 📂models
194
+ ┃ ┃ ┃ ┣ 📜index.ts
195
+ ┃ ┃ ┃ ┗ 📜user.ts
196
+ ┃ ┃ ┣ 📂queries
197
+ ┃ ┃ ┃ ┣ 📜index.ts
198
+ ┃ ┃ ┃ ┗ 📜user.ts
199
+ ┃ ┃ ┗ 📜index.ts
200
+ ┃ ┗ 📜index.ts
201
+ ┣ 📂network
202
+ ┃ ┣ 📂routes
203
+ ┃ ┃ ┣ 📂schemas
204
+ ┃ ┃ ┃ ┣ 📜index.ts
205
+ ┃ ┃ ┃ ┗ 📜user.ts
206
+ ┃ ┃ ┣ 📜docs.ts
207
+ ┃ ┃ ┣ 📜home.ts
208
+ ┃ ┃ ┣ 📜index.ts
209
+ ┃ ┃ ┗ 📜user.ts
210
+ ┃ ┣ 📜index.ts
211
+ ┃ ┣ 📜response.ts
212
+ ┃ ┣ 📜routes.ts
213
+ ┃ ┗ 📜server.ts
214
+ ┣ 📂services
215
+ ┃ ┣ 📂utils
216
+ ┃ ┃ ┣ 📂messages
217
+ ┃ ┃ ┃ ┣ 📜index.ts
218
+ ┃ ┃ ┃ ┗ 📜user.ts
219
+ ┃ ┃ ┗ 📜index.ts
220
+ ┃ ┣ 📜index.ts
221
+ ┃ ┗ 📜user.ts
222
+ ┗ 📜index.ts
223
+ 📜.env
224
+ 📜.eslintignore
225
+ 📜.eslintrc
226
+ 📜.gitignore
227
+ 📜CHANGELOG.md
228
+ 📜Dockerfile
229
+ 📜heroku.yml
230
+ 📜index.http
231
+ 📜LICENSE
232
+ 📜nodemon.json
233
+ 📜package.json
234
+ 📜README.md
235
+ 📜index.http
236
+ 📜tsconfig.base.json
237
+ 📜tsconfig.json
238
+ 📜webpack.config.js
239
+ 📜yarn.lock (or package-lock.json)
171
240
  ```
172
241
 
173
- 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:
174
-
175
- ```bash
176
- simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
177
- ```
242
+ 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.
178
243
 
179
244
  ### Some considerations
180
245
 
@@ -219,17 +284,14 @@ simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
219
284
 
220
285
  ## What is new?
221
286
 
222
- Please check the `changelog.md` file.
287
+ 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).
223
288
 
224
289
  ## <a name="notes"></a>Notes
225
290
 
226
291
  Here is the list of the packages that are being installed, as `devDependencies`:
227
292
 
228
- - [`@types/express`](https://www.npmjs.com/package/@types/express)
229
293
  - [`@types/http-errors`](https://www.npmjs.com/package/@types/http-errors)
230
- - [`@types/morgan`](https://www.npmjs.com/package/@types/morgan)
231
- - [`@types/node`](https://www.npmjs.com/package/@types/node/v/14.17.5)
232
- - [`@types/swagger-ui-express`](https://www.npmjs.com/package/@types/swagger-ui-express)
294
+ - [`@types/node`](https://www.npmjs.com/package/@types/node)
233
295
  - [`@typescript-eslint/eslint-plugin`](https://www.npmjs.com/package/@typescript-eslint/eslint-plugin)
234
296
  - [`@typescript-eslint/parser`](https://www.npmjs.com/package/@typescript-eslint/parser)
235
297
  - [`dotenv`](https://www.npmjs.com/package/dotenv)
@@ -252,15 +314,38 @@ Here is the list of the packages that are being installed, as `devDependencies`:
252
314
 
253
315
  As `dependencies`:
254
316
 
255
- - [`express`](https://expressjs.com/)
256
317
  - [`http-errors`](https://www.npmjs.com/package/http-errors)
257
- - [`joi`](https://joi.dev/api/?v=17.4.2)
258
318
  - [`mongoose`](https://mongoosejs.com/)
319
+
320
+ ### Express case
321
+
322
+ As `devDependencies`:
323
+
324
+ - [`@types/express`](https://www.npmjs.com/package/@types/express)
325
+ - [`@types/morgan`](https://www.npmjs.com/package/@types/morgan)
326
+ - [`@types/swagger-ui-express`](https://www.npmjs.com/package/@types/swagger-ui-express)
327
+
328
+ As `dependencies`:
329
+
330
+ - [`express`](https://expressjs.com/)
331
+ - [`joi`](https://joi.dev/api/?v=17.4.2)
259
332
  - [`morgan`](https://www.npmjs.com/package/morgan)
260
333
  - [`swagger-ui-express`](https://www.npmjs.com/package/swagger-ui-express)
261
334
 
335
+ ### Fastify case
336
+
337
+ As `dependencies`:
338
+
339
+ - [`@sinclair/typebox`](https://www.npmjs.com/package/@sinclair/typebox)
340
+ - [`fastify`](https://www.npmjs.com/package/fastify)
341
+ - [`fastify-swagger`](https://www.npmjs.com/package/fastify-swagger)
342
+
262
343
  Feel free to contribute to this project. Every contribution will be appreciated.
263
344
 
264
345
  ## Author
265
346
 
266
347
  - **Anthony Luzquiños** - _Initial Work_ - _Documentation_ - [AnthonyLzq](https://github.com/AnthonyLzq).
348
+
349
+ ## Contributors
350
+
351
+ - **Andree Anchi** - _Bug reports_ - [andreewaD](https://github.com/andreewD).
package/lib/index.js CHANGED
@@ -2,7 +2,7 @@ const readLineSync = require('readline-sync')
2
2
  const yargs = require('yargs/yargs')
3
3
  const { hideBin } = require('yargs/helpers')
4
4
 
5
- const installation = require('./src/installation')
5
+ const installation = require('./src')
6
6
 
7
7
  const CURRENT_YEAR = `${new Date().getFullYear()}`
8
8
  const argv = yargs(hideBin(process.argv))
@@ -50,6 +50,8 @@ const argv = yargs(hideBin(process.argv))
50
50
  'q',
51
51
  'Whether or not you want to be asked to answer the questions related to the project one by one'
52
52
  )
53
+ .alias('F', 'fastify')
54
+ .describe('F', 'Whether or not you want to use Fastify for your project')
53
55
  .default({
54
56
  H: false,
55
57
  n: false,
@@ -57,9 +59,10 @@ const argv = yargs(hideBin(process.argv))
57
59
  l: 'unlicensed',
58
60
  v: '0.1.0',
59
61
  f: 'src/index.ts',
60
- q: false
62
+ q: false,
63
+ F: false
61
64
  })
62
- .boolean(['H', 'n', 'q'])
65
+ .boolean(['H', 'n', 'q', 'F'])
63
66
  .help('h')
64
67
  .alias('h', 'help')
65
68
  .epilog('Developed by AnthonyLzq').argv
@@ -76,7 +79,8 @@ const config = {
76
79
  licenseYear: CURRENT_YEAR,
77
80
  npm: false,
78
81
  manager: 'yarn add',
79
- mainFile: 'src/index.ts'
82
+ mainFile: 'src/index.ts',
83
+ fastify: false
80
84
  }
81
85
  const UNLICENSED = 'unlicensed'
82
86
  const LICENSES = [
@@ -113,6 +117,22 @@ const main = async () => {
113
117
 
114
118
  if (config.npm) config.manager = 'npm i'
115
119
 
120
+ readLineSync.promptCLLoop(
121
+ {
122
+ express: () => true,
123
+ fastify: () => {
124
+ config.fastify = true
125
+
126
+ return true
127
+ }
128
+ },
129
+ {
130
+ caseSensitive: false,
131
+ limitMessage: 'That is not a valid option',
132
+ prompt: '> Express or Fastify? '
133
+ }
134
+ )
135
+
116
136
  readLineSync.promptLoop(
117
137
  input => {
118
138
  config.projectName = input.toLowerCase()
@@ -218,6 +238,8 @@ const main = async () => {
218
238
 
219
239
  if (argv.heroku) config.heroku = true
220
240
 
241
+ if (argv.fastify) config.fastify = true
242
+
221
243
  if (!argv.license || argv.license === UNLICENSED)
222
244
  console.log('License was not provided')
223
245
  else {
@@ -265,6 +287,8 @@ const main = async () => {
265
287
  else config.mainFile = argv.mainFile
266
288
  }
267
289
 
290
+ console.log(config)
291
+
268
292
  await installation(config)
269
293
  }
270
294
 
@@ -4,8 +4,12 @@ const exec = util.promisify(require('child_process').exec)
4
4
  const writeFile = require('../utils/writeFile')
5
5
 
6
6
  /*
7
+ * Express api:
7
8
  * src
8
9
  * |- @types:
10
+ * |- |- custom:
11
+ * |- |- |- request: content, file
12
+ * |- |- |- response: content, file
9
13
  * |- |- dto:
10
14
  * |- |- |- user: content, file
11
15
  * |- |- models:
@@ -27,9 +31,9 @@ const writeFile = require('../utils/writeFile')
27
31
  * | | | |- user: content, file
28
32
  * | | | |- index: content, file
29
33
  * | | |- home: content, file
30
- * | | |- user: content, file
31
34
  * | | |- index: content, file
32
- * | | |- response: content, file
35
+ * | | |- user: content, file
36
+ * | |- response: content, file
33
37
  * | |- router: content, file
34
38
  * | |- server: content, file
35
39
  * | |- index: content, file
@@ -49,12 +53,63 @@ const writeFile = require('../utils/writeFile')
49
53
  * index.http: content, file
50
54
  */
51
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
+
52
100
  /**
53
- * @param {String} projectName
54
- * @param {String} projectVersion
55
- * @param {String} email
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
56
106
  */
57
- module.exports = async (projectName, projectVersion, email) => {
107
+ module.exports = async ({
108
+ projectName,
109
+ projectVersion,
110
+ email,
111
+ fastify = false
112
+ }) => {
58
113
  const data = {
59
114
  '@types': {
60
115
  index: {
@@ -1245,6 +1300,464 @@ export { userSchema, storeUserSchema }
1245
1300
  }
1246
1301
  }
1247
1302
 
1303
+ const fastifyData = {
1304
+ network: {
1305
+ response: {
1306
+ content: `import { FastifyReply } from 'fastify'
1307
+
1308
+ const response = ({
1309
+ error,
1310
+ message,
1311
+ reply,
1312
+ status
1313
+ }: {
1314
+ error: boolean
1315
+ message: unknown
1316
+ reply: FastifyReply
1317
+ status: number
1318
+ }): void => {
1319
+ reply.code(status).send({ error, message })
1320
+ }
1321
+
1322
+ export { response }
1323
+ `,
1324
+ file: `${projectName}/src/network/response.ts`
1325
+ },
1326
+ router: {
1327
+ content: `import { FastifyInstance } from 'fastify'
1328
+ import { HttpError } from 'http-errors'
1329
+
1330
+ import { response } from './response'
1331
+ import { Home, User, Docs } from './routes'
1332
+
1333
+ const routers = [Docs, User]
1334
+
1335
+ const applyRoutes = (app: FastifyInstance): void => {
1336
+ Home(app)
1337
+ routers.forEach(router => router(app))
1338
+
1339
+ // Handling 404 error
1340
+ app.setNotFoundHandler((request, reply) => {
1341
+ response({
1342
+ error: true,
1343
+ message: 'This route does not exists',
1344
+ reply,
1345
+ status: 404
1346
+ })
1347
+ })
1348
+ app.setErrorHandler<HttpError>((error, request, reply) => {
1349
+ response({
1350
+ error: true,
1351
+ message: error.message,
1352
+ reply,
1353
+ status: error.status ?? 500
1354
+ })
1355
+ })
1356
+ }
1357
+
1358
+ export { applyRoutes }
1359
+ `,
1360
+ file: `${projectName}/src/network/router.ts`
1361
+ },
1362
+ server: {
1363
+ content: `import Fastify, { FastifyInstance } from 'fastify'
1364
+ import mongoose from 'mongoose'
1365
+
1366
+ import { applyRoutes } from './router'
1367
+
1368
+ const PORT = process.env.PORT ?? '1996'
1369
+
1370
+ class Server {
1371
+ private _app: FastifyInstance
1372
+ private _connection: mongoose.Connection | undefined
1373
+
1374
+ constructor() {
1375
+ this._app = Fastify({ logger: true })
1376
+ this._config()
1377
+ }
1378
+
1379
+ private _config() {
1380
+ this._app.addHook('preHandler', (req, reply, done) => {
1381
+ reply.header('Access-Control-Allow-Methods', 'GET, POST, PATCH, DELETE')
1382
+ reply.header('Access-Control-Allow-Origin', '*')
1383
+ reply.header(
1384
+ 'Access-Control-Allow-Headers',
1385
+ 'Authorization, Content-Type'
1386
+ )
1387
+ done()
1388
+ })
1389
+ applyRoutes(this._app)
1390
+ }
1391
+
1392
+ private async _mongo(): Promise<void> {
1393
+ this._connection = mongoose.connection
1394
+ const connection = {
1395
+ keepAlive: true,
1396
+ useNewUrlParser: true,
1397
+ useUnifiedTopology: true
1398
+ }
1399
+ this._connection.on('connected', () => {
1400
+ this._app.log.info('Mongo connection established.')
1401
+ })
1402
+ this._connection.on('reconnected', () => {
1403
+ this._app.log.info('Mongo connection reestablished')
1404
+ })
1405
+ this._connection.on('disconnected', () => {
1406
+ this._app.log.info('Mongo connection disconnected')
1407
+ this._app.log.info('Trying to reconnected to Mongo...')
1408
+ setTimeout(() => {
1409
+ mongoose.connect(process.env.MONGO_URI as string, {
1410
+ ...connection,
1411
+ connectTimeoutMS: 3000,
1412
+ socketTimeoutMS: 3000
1413
+ })
1414
+ }, 3000)
1415
+ })
1416
+ this._connection.on('close', () => {
1417
+ this._app.log.info('Mongo connection closed')
1418
+ })
1419
+ this._connection.on('error', (e: Error) => {
1420
+ this._app.log.info('Mongo connection error:')
1421
+ this._app.log.error(e)
1422
+ })
1423
+ await mongoose.connect(process.env.MONGO_URI as string, connection)
1424
+ }
1425
+
1426
+ public async start(): Promise<void> {
1427
+ try {
1428
+ await this._app.listen(PORT)
1429
+ this._mongo()
1430
+ } catch (e) {
1431
+ console.error(e)
1432
+ }
1433
+ }
1434
+ }
1435
+
1436
+ const server = new Server()
1437
+
1438
+ export { server as Server }
1439
+ `,
1440
+ file: `${projectName}/src/network/server.ts`
1441
+ }
1442
+ },
1443
+ 'network/routes': {
1444
+ docs: {
1445
+ content: `import { FastifyInstance } from 'fastify'
1446
+ import fastifySwagger from 'fastify-swagger'
1447
+
1448
+ const Docs = (app: FastifyInstance, prefix = '/api'): void => {
1449
+ app.register(fastifySwagger, {
1450
+ routePrefix: \`\${prefix}/docs\`,
1451
+ openapi: {
1452
+ info: {
1453
+ title: 'Test swagger',
1454
+ description: 'Testing the Fastify swagger API',
1455
+ version: '0.1.0',
1456
+ contact: {
1457
+ email: 'sluzquinosa@uni.pe'
1458
+ },
1459
+ license: {
1460
+ name: 'MIT',
1461
+ url: 'https://opensource.org/licenses/MIT'
1462
+ }
1463
+ },
1464
+ servers: [
1465
+ {
1466
+ url: 'http://localhost:1996/api',
1467
+ description: 'test-fastify local API'
1468
+ }
1469
+ ],
1470
+ tags: [
1471
+ {
1472
+ name: 'user',
1473
+ description: 'User related endpoints'
1474
+ }
1475
+ ]
1476
+ },
1477
+ exposeRoute: true
1478
+ })
1479
+ }
1480
+
1481
+ export { Docs }
1482
+ `,
1483
+ file: `${projectName}/src/network/routes/docs.ts`
1484
+ },
1485
+ home: {
1486
+ content: `import { FastifyInstance } from 'fastify'
1487
+ import { response } from 'network/response'
1488
+
1489
+ const Home = (app: FastifyInstance, prefix = '/'): void => {
1490
+ app.get(\`\${prefix}\`, (request, reply) => {
1491
+ response({
1492
+ error: false,
1493
+ message: 'Welcome to your Fastify Backend!',
1494
+ reply,
1495
+ status: 200
1496
+ })
1497
+ })
1498
+ }
1499
+
1500
+ export { Home }
1501
+ `,
1502
+ file: `${projectName}/src/network/routes/home.ts`
1503
+ },
1504
+ index: {
1505
+ content: `export * from './home'
1506
+ export * from './user'
1507
+ export * from './docs'
1508
+ `,
1509
+ file: `${projectName}/src/network/routes/index.ts`
1510
+ },
1511
+ user: {
1512
+ content: `import { FastifyInstance } from 'fastify'
1513
+
1514
+ import { response } from 'network/response'
1515
+ import { userSchema, idSchema, storeUserSchema } from './schemas'
1516
+ import { UserService } from 'services'
1517
+
1518
+ const User = (app: FastifyInstance, prefix = '/api'): void => {
1519
+ app
1520
+ .post<{ Body: { args: Omit<DtoUser, 'id'> } }>(
1521
+ \`\${prefix}/users\`,
1522
+ {
1523
+ schema: {
1524
+ body: {
1525
+ args: storeUserSchema
1526
+ },
1527
+ response: {
1528
+ 200: {
1529
+ error: {
1530
+ type: 'boolean'
1531
+ },
1532
+ message: userSchema
1533
+ }
1534
+ },
1535
+ tags: ['user']
1536
+ }
1537
+ },
1538
+ async (request, reply) => {
1539
+ const {
1540
+ body: {
1541
+ args: { lastName, name }
1542
+ }
1543
+ } = request
1544
+ const us = new UserService({ lastName, name })
1545
+ const user = await us.process({ type: 'store' })
1546
+
1547
+ response({
1548
+ error: false,
1549
+ message: user,
1550
+ reply,
1551
+ status: 200
1552
+ })
1553
+ }
1554
+ )
1555
+ .get(
1556
+ \`\${prefix}/users\`,
1557
+ {
1558
+ schema: {
1559
+ response: {
1560
+ 200: {
1561
+ error: {
1562
+ type: 'boolean'
1563
+ },
1564
+ message: {
1565
+ type: 'array',
1566
+ items: userSchema
1567
+ }
1568
+ }
1569
+ },
1570
+ tags: ['user']
1571
+ }
1572
+ },
1573
+ async (request, reply) => {
1574
+ const us = new UserService()
1575
+ const users = await us.process({ type: 'getAll' })
1576
+
1577
+ response({
1578
+ error: false,
1579
+ message: users,
1580
+ reply,
1581
+ status: 200
1582
+ })
1583
+ }
1584
+ )
1585
+ .delete(
1586
+ \`\${prefix}/users\`,
1587
+ {
1588
+ schema: {
1589
+ response: {
1590
+ 200: {
1591
+ error: {
1592
+ type: 'boolean'
1593
+ },
1594
+ message: {
1595
+ type: 'string'
1596
+ }
1597
+ }
1598
+ },
1599
+ tags: ['user']
1600
+ }
1601
+ },
1602
+ async (request, reply) => {
1603
+ const us = new UserService()
1604
+ const result = await us.process({ type: 'deleteAll' })
1605
+
1606
+ response({
1607
+ error: false,
1608
+ message: result,
1609
+ reply,
1610
+ status: 200
1611
+ })
1612
+ }
1613
+ )
1614
+ .get<{ Params: { id: string } }>(
1615
+ \`\${prefix}/user/:id\`,
1616
+ {
1617
+ schema: {
1618
+ params: {
1619
+ id: idSchema
1620
+ },
1621
+ response: {
1622
+ 200: {
1623
+ error: {
1624
+ type: 'boolean'
1625
+ },
1626
+ message: userSchema
1627
+ }
1628
+ },
1629
+ tags: ['user']
1630
+ }
1631
+ },
1632
+ async (request, reply) => {
1633
+ const {
1634
+ params: { id }
1635
+ } = request
1636
+ const us = new UserService({ id })
1637
+ const user = await us.process({ type: 'getOne' })
1638
+
1639
+ response({
1640
+ error: false,
1641
+ message: user,
1642
+ reply,
1643
+ status: 200
1644
+ })
1645
+ }
1646
+ )
1647
+ .patch<{ Body: { args: Omit<DtoUser, 'id'> }; Params: { id: string } }>(
1648
+ \`\${prefix}/user/:id\`,
1649
+ {
1650
+ schema: {
1651
+ body: {
1652
+ args: userSchema
1653
+ },
1654
+ params: {
1655
+ id: idSchema
1656
+ },
1657
+ response: {
1658
+ 200: {
1659
+ error: {
1660
+ type: 'boolean'
1661
+ },
1662
+ message: userSchema
1663
+ }
1664
+ },
1665
+ tags: ['user']
1666
+ }
1667
+ },
1668
+ async (request, reply) => {
1669
+ const {
1670
+ body: {
1671
+ args: { name, lastName }
1672
+ },
1673
+ params: { id }
1674
+ } = request
1675
+ const us = new UserService({ name, lastName, id })
1676
+ const user = await us.process({ type: 'update' })
1677
+
1678
+ response({
1679
+ error: false,
1680
+ message: user,
1681
+ reply,
1682
+ status: 200
1683
+ })
1684
+ }
1685
+ )
1686
+ .delete<{ Params: { id: string } }>(
1687
+ \`\${prefix}/user/:id\`,
1688
+ {
1689
+ schema: {
1690
+ params: {
1691
+ id: idSchema
1692
+ },
1693
+ response: {
1694
+ 200: {
1695
+ error: {
1696
+ type: 'boolean'
1697
+ },
1698
+ message: {
1699
+ type: 'string'
1700
+ }
1701
+ }
1702
+ },
1703
+ tags: ['user']
1704
+ }
1705
+ },
1706
+ async (request, reply) => {
1707
+ const {
1708
+ params: { id }
1709
+ } = request
1710
+ const us = new UserService({ id })
1711
+ const result = await us.process({ type: 'delete' })
1712
+
1713
+ response({
1714
+ error: false,
1715
+ message: result,
1716
+ reply,
1717
+ status: 200
1718
+ })
1719
+ }
1720
+ )
1721
+ }
1722
+
1723
+ export { User }
1724
+ `,
1725
+ file: `${projectName}/src/network/routes/user.ts`
1726
+ }
1727
+ },
1728
+ 'network/routes/schemas': {
1729
+ index: {
1730
+ content: `import { Type } from '@sinclair/typebox'
1731
+
1732
+ const idSchema = Type.String({ minLength: 24, maxLength: 24 })
1733
+
1734
+ export { idSchema }
1735
+ export * from './user'
1736
+ `,
1737
+ file: `${projectName}/src/network/routes/schemas/index.ts`
1738
+ },
1739
+ user: {
1740
+ content: `import { Type } from '@sinclair/typebox'
1741
+
1742
+ const userSchema = Type.Object({
1743
+ id: Type.Optional(Type.String({ minLength: 24, maxLength: 24 })),
1744
+ lastName: Type.Optional(Type.String()),
1745
+ name: Type.Optional(Type.String()),
1746
+ updatedAt: Type.Optional(Type.String())
1747
+ })
1748
+
1749
+ const storeUserSchema = Type.Object({
1750
+ lastName: Type.String(),
1751
+ name: Type.String()
1752
+ })
1753
+
1754
+ export { userSchema, storeUserSchema }
1755
+ `,
1756
+ file: `${projectName}/src/network/routes/schemas/user.ts`
1757
+ }
1758
+ }
1759
+ }
1760
+
1248
1761
  const expressFolders = `${projectName}/src/utils`
1249
1762
 
1250
1763
  const createFoldersCommands = `mkdir ${projectName}/src \
@@ -1262,7 +1775,7 @@ ${projectName}/src/network/routes/schemas \
1262
1775
  ${projectName}/src/services \
1263
1776
  ${projectName}/src/services/utils \
1264
1777
  ${projectName}/src/services/utils/messages \
1265
- ${expressFolders}
1778
+ ${fastify ? '' : `${expressFolders}`}
1266
1779
  `
1267
1780
 
1268
1781
  if (os.platform() === 'win32')
@@ -1272,16 +1785,6 @@ ${expressFolders}
1272
1785
  // /@types
1273
1786
  await writeFile(data['@types'].index.file, data['@types'].index.content)
1274
1787
 
1275
- // /@types/custom
1276
- await writeFile(
1277
- expressData['@types/custom'].request.file,
1278
- expressData['@types/custom'].request.content
1279
- )
1280
- await writeFile(
1281
- expressData['@types/custom'].response.file,
1282
- expressData['@types/custom'].response.content
1283
- )
1284
-
1285
1788
  // /@types/dto
1286
1789
  await writeFile(data['@types/dto'].user.file, data['@types/dto'].user.content)
1287
1790
 
@@ -1336,53 +1839,112 @@ ${expressFolders}
1336
1839
 
1337
1840
  // /network
1338
1841
  await writeFile(data.network.index.file, data.network.index.content)
1339
- await writeFile(
1340
- expressData.network.response.file,
1341
- expressData.network.response.content
1342
- )
1343
- await writeFile(
1344
- expressData.network.router.file,
1345
- expressData.network.router.content
1346
- )
1347
- await writeFile(
1348
- expressData.network.server.file,
1349
- expressData.network.server.content
1350
- )
1351
-
1352
- // /network/routes
1353
- await writeFile(
1354
- expressData['network/routes'].home.file,
1355
- expressData['network/routes'].home.content
1356
- )
1357
- await writeFile(
1358
- expressData['network/routes'].user.file,
1359
- expressData['network/routes'].user.content
1360
- )
1361
- await writeFile(
1362
- expressData['network/routes'].index.file,
1363
- expressData['network/routes'].index.content
1364
- )
1365
-
1366
- // /network/routes/schemas
1367
- await writeFile(
1368
- expressData['network/routes/schemas'].index.file,
1369
- expressData['network/routes/schemas'].index.content
1370
- )
1371
- await writeFile(
1372
- expressData['network/routes/schemas'].user.file,
1373
- expressData['network/routes/schemas'].user.content
1374
- )
1375
1842
 
1376
1843
  // /test
1377
1844
  await writeFile(data.test.index.file, data.test.index.content)
1378
1845
 
1379
- // /utils
1380
- await writeFile(expressData.utils.docs.file, expressData.utils.docs.content)
1381
- await writeFile(expressData.utils.index.file, expressData.utils.index.content)
1382
-
1383
1846
  // .env
1384
1847
  await writeFile(data['.env'].file, data['.env'].content)
1385
1848
 
1386
1849
  // index
1387
1850
  await writeFile(data.index.file, data.index.content)
1851
+
1852
+ if (fastify) {
1853
+ // /network
1854
+ await writeFile(
1855
+ fastifyData.network.response.file,
1856
+ fastifyData.network.response.content
1857
+ )
1858
+ await writeFile(
1859
+ fastifyData.network.router.file,
1860
+ fastifyData.network.router.content
1861
+ )
1862
+ await writeFile(
1863
+ fastifyData.network.server.file,
1864
+ fastifyData.network.server.content
1865
+ )
1866
+
1867
+ // /network/routes
1868
+ await writeFile(
1869
+ fastifyData['network/routes'].docs.file,
1870
+ fastifyData['network/routes'].docs.content
1871
+ )
1872
+ await writeFile(
1873
+ fastifyData['network/routes'].home.file,
1874
+ fastifyData['network/routes'].home.content
1875
+ )
1876
+ await writeFile(
1877
+ fastifyData['network/routes'].user.file,
1878
+ fastifyData['network/routes'].user.content
1879
+ )
1880
+ await writeFile(
1881
+ fastifyData['network/routes'].index.file,
1882
+ fastifyData['network/routes'].index.content
1883
+ )
1884
+
1885
+ // /network/routes/schemas
1886
+ await writeFile(
1887
+ fastifyData['network/routes/schemas'].index.file,
1888
+ fastifyData['network/routes/schemas'].index.content
1889
+ )
1890
+ await writeFile(
1891
+ fastifyData['network/routes/schemas'].user.file,
1892
+ fastifyData['network/routes/schemas'].user.content
1893
+ )
1894
+ } else {
1895
+ // /network
1896
+ await writeFile(
1897
+ expressData.network.response.file,
1898
+ expressData.network.response.content
1899
+ )
1900
+ await writeFile(
1901
+ expressData.network.router.file,
1902
+ expressData.network.router.content
1903
+ )
1904
+ await writeFile(
1905
+ expressData.network.server.file,
1906
+ expressData.network.server.content
1907
+ )
1908
+
1909
+ // /network/routes
1910
+ await writeFile(
1911
+ expressData['network/routes'].home.file,
1912
+ expressData['network/routes'].home.content
1913
+ )
1914
+ await writeFile(
1915
+ expressData['network/routes'].user.file,
1916
+ expressData['network/routes'].user.content
1917
+ )
1918
+ await writeFile(
1919
+ expressData['network/routes'].index.file,
1920
+ expressData['network/routes'].index.content
1921
+ )
1922
+
1923
+ // /network/routes/schemas
1924
+ await writeFile(
1925
+ expressData['network/routes/schemas'].index.file,
1926
+ expressData['network/routes/schemas'].index.content
1927
+ )
1928
+ await writeFile(
1929
+ expressData['network/routes/schemas'].user.file,
1930
+ expressData['network/routes/schemas'].user.content
1931
+ )
1932
+
1933
+ // /utils
1934
+ await writeFile(expressData.utils.docs.file, expressData.utils.docs.content)
1935
+ await writeFile(
1936
+ expressData.utils.index.file,
1937
+ expressData.utils.index.content
1938
+ )
1939
+
1940
+ // /@types/custom
1941
+ await writeFile(
1942
+ expressData['@types/custom'].request.file,
1943
+ expressData['@types/custom'].request.content
1944
+ )
1945
+ await writeFile(
1946
+ expressData['@types/custom'].response.file,
1947
+ expressData['@types/custom'].response.content
1948
+ )
1949
+ }
1388
1950
  }
@@ -18,7 +18,10 @@ module.exports = async ({
18
18
  }
19
19
 
20
20
  data.content = `{
21
- "name": "${projectName.toLowerCase().replace(/ /g, '-')}",
21
+ "name": "${projectName
22
+ .toLowerCase()
23
+ .replaceAll(' ', '-')
24
+ .replaceAll('/', '-')}",
22
25
  "version": "${projectVersion}",
23
26
  "main": "${mainFile}",
24
27
  "description": "${projectDescription}",
package/lib/src/index.js CHANGED
@@ -14,7 +14,7 @@ const eslint = require('./functions/eslint')
14
14
  const webpack = require('./functions/webpack')
15
15
  const docker = require('./functions/docker')
16
16
  const herokuF = require('./functions/heroku')
17
- const express = require('./functions/api')
17
+ const api = require('./functions/api')
18
18
 
19
19
  /**
20
20
  * @param {Number} process number of process
@@ -45,7 +45,8 @@ module.exports = async ({
45
45
  version,
46
46
  licenseYear,
47
47
  manager,
48
- mainFile
48
+ mainFile,
49
+ fastify
49
50
  }) => {
50
51
  const process = 4
51
52
  let i = 0
@@ -57,9 +58,13 @@ module.exports = async ({
57
58
  )
58
59
 
59
60
  const expressProdPackages = 'express joi morgan swagger-ui-express'
60
- const prodPackages = `${manager} http-errors mongoose ${expressProdPackages}`
61
+ const fastifyProdPackages = '@sinclair/typebox fastify fastify-swagger'
62
+ const prodPackages = `${manager} http-errors mongoose ${
63
+ fastify ? fastifyProdPackages : expressProdPackages
64
+ }`
61
65
 
62
66
  const expressDevPackages = `@types/express @types/morgan @types/swagger-ui-express`
67
+ const fastifyDevPackages = ''
63
68
  const devPackages = `${manager} -D \
64
69
  @types/http-errors \
65
70
  @types/node \
@@ -84,7 +89,7 @@ typescript \
84
89
  webpack \
85
90
  webpack-cli \
86
91
  webpack-node-externals \
87
- ${expressDevPackages}`
92
+ ${fastify ? fastifyDevPackages : expressDevPackages}`
88
93
 
89
94
  bar.start(process, i)
90
95
 
@@ -109,7 +114,7 @@ ${expressDevPackages}`
109
114
  eslint(projectName),
110
115
  webpack(projectName),
111
116
  docker(projectName),
112
- express(projectName, version, email),
117
+ api({ projectName, version, email, fastify }),
113
118
  exec('git init', { cwd: `./${projectName}` })
114
119
  ]
115
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthonylzq/simba.js",
3
- "version": "2.1.1",
3
+ "version": "3.2.0",
4
4
  "description": "set up a modern backend app by running one command",
5
5
  "main": "lib/index.js",
6
6
  "directories": {
@@ -10,10 +10,16 @@
10
10
  "scripts": {
11
11
  "service": "node ./bin",
12
12
  "release": "standard-version",
13
- "test": "npm run rm && node -r dotenv/config ./bin -N example -D 'This is a test' -a AnthonyLzq -e sluzquinosa@uni.pe -l mit -H && npm run rm-git-example",
13
+ "test": "npm run rm && npm run test-express && npm run test-fastify",
14
+ "test-express": "npm run rm-express && npm run cd-mv-example && node -r dotenv/config ./bin -N example/express -D 'This is a test using express' -a AnthonyLzq -e sluzquinosa@uni.pe -l mit -H && npm run rm-git-express",
15
+ "test-fastify": "npm run rm-fastify && npm run cd-mv-example && node -r dotenv/config ./bin -N example/fastify -D 'This is a test using fastify' -a AnthonyLzq -e sluzquinosa@uni.pe -l mit -H -F && npm run rm-git-fastify",
14
16
  "lint": "eslint --ext js lib/ --fix",
15
17
  "rm": "if [ -d \"example\" ]; then rm -rf example; fi",
16
- "rm-git-example": "if [ -d \"example/.git\" ]; then rm -rf example/.git; fi"
18
+ "rm-express": "if [ -d \"example/express\" ]; then rm -rf example/express; fi",
19
+ "rm-fastify": "if [ -d \"example/fastify\" ]; then rm -rf example/fastify; fi",
20
+ "rm-git-express": "if [ -d \"example/express/.git\" ]; then rm -rf example/express/.git; fi",
21
+ "rm-git-fastify": "if [ -d \"example/fastify/.git\" ]; then rm -rf example/fastify/.git; fi",
22
+ "cd-mv-example": "if [ ! -d \"example\" ]; then mkdir example && cd example; fi"
17
23
  },
18
24
  "bin": {
19
25
  "simba": "./bin/index.js"