@anthonylzq/simba.js 1.10.0 → 2.0.3

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
@@ -6,7 +6,7 @@ Set up a modern backend app by running one command. This project has the goal to
6
6
 
7
7
  - `.env`
8
8
  - `.eslintignore`
9
- - `.eslintrc.js`
9
+ - `.eslintrc`
10
10
  - `.gitignore`
11
11
  - `CHANGELOG.md`
12
12
  - `Dockerfile`
@@ -15,15 +15,17 @@ Set up a modern backend app by running one command. This project has the goal to
15
15
  - `nodemon.json`
16
16
  - `package.json`
17
17
  - `README.md`
18
+ - `tsconfig.base.json`
18
19
  - `tsconfig.json`
19
20
  - `webpack.config.js`
21
+ - `yarn.lock` (or `package-lock.json`)
20
22
 
21
23
  ## Installation
22
24
 
23
25
  This package is meant to be installed globally in your computer by using:
24
26
 
25
27
  ```bash
26
- npm i -g simba.js
28
+ npm i -g @anthonylzq/simba.js
27
29
  ```
28
30
 
29
31
  ## Usage
@@ -86,8 +88,8 @@ Options:
86
88
  -h, --help Show help [boolean]
87
89
 
88
90
  Examples:
89
- simba -N "Project Name" -D "Project description -a Anthony -e
90
- sluzquinosa@uni.pe"
91
+ simba -N 'Project Name' -D 'Project description' -a Anthony -e
92
+ sluzquinosa@uni.pe
91
93
 
92
94
  Developed by AnthonyLzq
93
95
  ```
@@ -95,34 +97,56 @@ Developed by AnthonyLzq
95
97
  Regardless of the option chosen, a new folder will be generated with the name of the project, it will contain the following structure:
96
98
 
97
99
  ```
98
- 📦node_modules
99
- 📦src
100
+ 📂node_modules
101
+ 📂src
100
102
  ┣ 📂@types
101
- ┃ ┣ 📜index.d.ts
102
- 📂controllers
103
- 📜index.ts
104
- 📜user.ts
105
- 📂dto-interfaces
106
- ┃ ┣ 📜index.ts
107
- ┃ ┗ 📜user.dto.ts
108
- 📂models
109
- 📜index.ts
110
- 📜user.ts
103
+ ┃ ┣ 📂custom
104
+ ┃ ┃ 📜request.d.ts
105
+ 📜response.d.ts
106
+ 📂dto
107
+ ┃ ┗ 📜user.d.ts
108
+ ┃ ┣ 📂models
109
+ ┗ 📜user.d.ts
110
+ ┗ 📜index.d.ts
111
+ 📂database
112
+ 📂mongo
113
+ ┃ ┃ ┣ 📂models
114
+ ┃ ┃ ┃ ┣ 📜index.ts
115
+ ┃ ┃ ┃ ┗ 📜user.ts
116
+ ┃ ┃ ┣ 📂queries
117
+ ┃ ┃ ┃ ┣ 📜index.ts
118
+ ┃ ┃ ┃ ┗ 📜user.ts
119
+ ┃ ┃ ┗ 📜index.ts
120
+ ┃ ┗ 📜index.ts
111
121
  ┣ 📂network
122
+ ┃ ┣ 📂routes
123
+ ┃ ┃ ┣ 📂schemas
124
+ ┃ ┃ ┃ ┣ 📜index.ts
125
+ ┃ ┃ ┃ ┗ 📜user.ts
126
+ ┃ ┃ ┣ 📜home.ts
127
+ ┃ ┃ ┣ 📜index.ts
128
+ ┃ ┃ ┗ 📜user.ts
112
129
  ┃ ┣ 📜index.ts
130
+ ┃ ┣ 📜response.ts
113
131
  ┃ ┣ 📜routes.ts
114
132
  ┃ ┗ 📜server.ts
115
- ┣ 📂routes
116
- ┃ ┣ 📜home.ts
133
+ ┣ 📂services
134
+ ┃ ┣ 📂utils
135
+ ┃ ┃ ┣ 📂messages
136
+ ┃ ┃ ┃ ┣ 📜index.ts
137
+ ┃ ┃ ┃ ┗ 📜user.ts
138
+ ┃ ┃ ┗ 📜index.ts
117
139
  ┃ ┣ 📜index.ts
118
140
  ┃ ┗ 📜user.ts
141
+ ┣ 📂test
142
+ ┃ ┗ 📜test.http
119
143
  ┣ 📂utils
120
- ┃ ┣ 📜index.ts
121
- ┃ ┗ 📜response.ts
144
+ ┃ ┣ 📜docs.json
145
+ ┃ ┗ 📜index.ts
122
146
  ┗ 📜index.ts
123
147
  📜.env
124
148
  📜.eslintignore
125
- 📜.eslintrc.js
149
+ 📜.eslintrc
126
150
  📜.gitignore
127
151
  📜CHANGELOG.md
128
152
  📜Dockerfile
@@ -131,6 +155,7 @@ Regardless of the option chosen, a new folder will be generated with the name of
131
155
  📜nodemon.json
132
156
  📜package.json
133
157
  📜README.md
158
+ 📜tsconfig.base.json
134
159
  📜tsconfig.json
135
160
  📜webpack.config.js
136
161
  📜yarn.lock (or package-lock.json)
@@ -160,8 +185,8 @@ simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
160
185
 
161
186
  ### Some considerations
162
187
 
163
- - This project is based in other project from my own, [`typescript-project-generator`](https://www.npmjs.com/package/typescript-project-generator), but only considering the `express-mongoose-node` part.
164
- - You are able to run a server that has one main route, `home` (`/`), `user` (`api/user` or `api/user/:userId`) and `docs` (`api/docs`).
188
+ - 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.
189
+ - You are able to run a server that has one main route, `home` (`/`), `user` (`api/user` or `api/user/:id`) and `docs` (`api/docs`).
165
190
  - 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:
166
191
 
167
192
  ```bash
@@ -182,11 +207,16 @@ simba -N myProject -D 'This is a test' -a myName -e myEmail@email.com -H
182
207
  // Some more code...
183
208
 
184
209
  // another file
185
- globalStringVariable = 'Hi mom, I am global'
210
+ global.globalStringVariable = 'Hi mom, I am global'
186
211
  console.log({ globalStringVariable })
187
212
  ```
188
213
 
189
- - The provided project structure is inspired in my personal experience as [`Node.js`](https://nodejs.org/en/) developer and the [`Nest`](https://nestjs.com/) framework.
214
+ - The provided project structure is inspired in my personal experience as [`Node.js`](https://nodejs.org/en/) developer and the [`Nest`](https://nestjs.com/) framework. It follows a layered architecture:
215
+
216
+ 1. Presentation layer (network layer): it is represented by the network folder, which contains the routes and the necessary schemas for each route.
217
+ 2. Business layer (services layer): it is represented by the services folder, which contains all the code related to the business logic of your application.
218
+ 3. Persistance layer (database layer): it is represented by the database folder, which contains the database connection, models and queries (that will be used by the services). Multiple database connection are possible and should be implemented here.
219
+
190
220
  - The server is fully tested and has no errors (at least for now), feel free to report one [here](https://github.com/AnthonyLzq/simba.js/issues).
191
221
  - Support for windows and linux platforms is available.
192
222
  - To check the content of the files generated, please check the `example` folder.
@@ -215,8 +245,6 @@ Here is the list of the packages that are being installed, as `devDependencies`:
215
245
  - [`eslint-config-standard`](https://www.npmjs.com/package/eslint-config-standard)
216
246
  - [`eslint-plugin-import`](https://www.npmjs.com/package/eslint-plugin-import)
217
247
  - [`eslint-plugin-prettier`](https://www.npmjs.com/package/eslint-plugin-prettier)
218
- - [`eslint-plugin-sort-keys-fix`](https://www.npmjs.com/package/eslint-plugin-sort-keys-fix)
219
- - [`eslint-plugin-typescript-sort-keys`](https://www.npmjs.com/package/eslint-plugin-typescript-sort-keys)
220
248
  - [`nodemon`](https://www.npmjs.com/package/nodemon)
221
249
  - [`prettier`](https://www.npmjs.com/package/prettier)
222
250
  - [`standard-version`](https://www.npmjs.com/package/standard-version)
package/lib/index.js CHANGED
@@ -12,7 +12,7 @@ const argv = yargs(hideBin(process.argv))
12
12
  'simba [options] (if you it installed globally) or only simba if you want to be asked for the options one by one'
13
13
  )
14
14
  .example(
15
- 'simba -N "Project Name" -D "Project description -a Anthony -e sluzquinosa@uni.pe"'
15
+ "simba -N 'Project Name' -D 'Project description' -a Anthony -e sluzquinosa@uni.pe"
16
16
  )
17
17
  .alias('N', 'projectName')
18
18
  .nargs('N', 1)
@@ -14,11 +14,11 @@ COPY package.json ./
14
14
 
15
15
  RUN yarn install --prod
16
16
 
17
- RUN yarn add webpack webpack-node-externals -D
17
+ RUN yarn add webpack webpack-node-externals tsconfig-paths-webpack-plugin -D
18
18
 
19
19
  RUN yarn build
20
20
 
21
- RUN yarn remove webpack webpack-node-externals
21
+ RUN yarn remove webpack webpack-node-externals tsconfig-paths-webpack-plugin
22
22
 
23
23
  COPY dist /app/dist
24
24
 
@@ -74,7 +74,7 @@ module.exports = async projectName => {
74
74
  }
75
75
  }
76
76
  `,
77
- eslintFile: '.eslintrc.js',
77
+ eslintFile: '.eslintrc',
78
78
  eslintIgnoreContent: '/dist',
79
79
  eslintIgnoreFile: '.eslintignore'
80
80
  }
@@ -1,3 +1,4 @@
1
+ const os = require('os')
1
2
  const util = require('util')
2
3
  const exec = util.promisify(require('child_process').exec)
3
4
  const writeFile = require('../utils/writeFile')
@@ -5,30 +6,39 @@ const writeFile = require('../utils/writeFile')
5
6
  /*
6
7
  * src
7
8
  * |- @types:
9
+ * |- |- dto:
10
+ * |- |- |- user: content, file
11
+ * |- |- models:
12
+ * |- |- |- user: content, file
8
13
  * | |- index: content, file
9
- * |- controllers:
10
- * | |- utils:
11
- * | | |- messages:
14
+ * |- database:
15
+ * | |- mongo:
16
+ * | |- |- models:
17
+ * | |- |- |- index: content, file
18
+ * | |- |- |- user: content, file
19
+ * | |- |- queries:
20
+ * | |- |- |- index: content, file
21
+ * | |- |- |- user: content, file
22
+ * | |- |- index: content, file
23
+ * | |- index: content, file
24
+ * |- network:
25
+ * | |- routes:
26
+ * | | |- schemas:
12
27
  * | | | |- user: content, file
13
28
  * | | | |- index: content, file
29
+ * | | |- home: content, file
30
+ * | | |- user: content, file
14
31
  * | | |- index: content, file
15
- * | |- user: content, file
16
- * | |- index: content, file
17
- * |- dto-interfaces:
18
- * | |- user: content, file
19
- * | |- index: content, file
20
- * |- models:
21
- * | |- user: content, file
22
- * | |- index: content, file
23
- * |- network:
32
+ * | | |- response: content, file
33
+ * | |- router: content, file
24
34
  * | |- server: content, file
25
- * | |- routes: content, file
26
- * | |- index: content, file
27
- * |- routes:
28
- * | |- home: content, file
29
- * | |- user: content, file
30
35
  * | |- index: content, file
31
- * |- schemas:
36
+ * |- services:
37
+ * | |- utils:
38
+ * | | |- messages:
39
+ * | | | |- user: content, file
40
+ * | | | |- index: content, file
41
+ * | | |- index: content, file
32
42
  * | |- user: content, file
33
43
  * | |- index: content, file
34
44
  * |- test:
@@ -50,268 +60,86 @@ module.exports = async (projectName, projectVersion, email) => {
50
60
  '@types': {
51
61
  index: {
52
62
  content: `/* eslint-disable no-var */
53
- import { IncomingHttpHeaders } from 'http'
54
- import { Request, Response } from 'express'
55
-
56
- import { DtoUser } from 'dto-interfaces'
57
-
58
- declare global {
59
- interface ResponseProps {
60
- error: boolean
61
- message: unknown
62
- res: Response
63
- status: number
64
- }
65
- // This variable is global, so it will be available everywhere in the code
66
- var response: ({ error, message, res, status }: ResponseProps) => void
67
-
68
- // We can personalize the response and request objects in case we need it by
69
- // adding new optional attributes to this interface
70
- interface CustomResponse extends Response {
71
- newValue?: string
72
- }
73
-
74
- interface CustomRequest extends Request {
75
- body: {
76
- args?: DtoUser
77
- }
78
- // We can add custom headers via intersection, remember that for some reason
79
- // headers must be in Snake-Pascal-Case
80
- headers: IncomingHttpHeaders & {
81
- 'Custom-Header'?: string
82
- }
83
- }
84
- }
63
+ declare global {}
85
64
 
86
65
  export {}
87
66
  `,
88
67
  file: `${projectName}/src/@types/index.d.ts`
89
68
  }
90
69
  },
91
- controllers: {
92
- index: {
93
- content: `import { User } from './user'
94
-
95
- export { User }
96
- `,
97
- file: `${projectName}/src/controllers/index.ts`
98
- },
70
+ '@types/dto': {
99
71
  user: {
100
- content: `import httpErrors from 'http-errors'
101
-
102
- import { DtoUser } from 'dto-interfaces'
103
- import { IUser, UserModel } from 'models'
104
- import { EFU, MFU, GE, errorHandling } from './utils'
105
-
106
- type Process = {
107
- type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
72
+ content: `interface DtoUser {
73
+ id?: string
74
+ lastName?: string
75
+ name?: string
108
76
  }
77
+ `,
78
+ file: `${projectName}/src/@types/dto/user.d.ts`
79
+ }
80
+ },
81
+ '@types/custom': {
82
+ request: {
83
+ content: `type ExpressRequest = import('express').Request
109
84
 
110
- class User {
111
- private _args: DtoUser | null
112
-
113
- constructor(args: DtoUser | null = null) {
114
- this._args = args
115
- }
116
-
117
- public process({
118
- type
119
- }: Process): Promise<string> | Promise<IUser[]> | Promise<IUser> {
120
- switch (type) {
121
- case 'store':
122
- return this._store()
123
- case 'getAll':
124
- return this._getAll()
125
- case 'deleteAll':
126
- return this._deleteAll()
127
- case 'getOne':
128
- return this._getOne()
129
- case 'update':
130
- return this._update()
131
- case 'delete':
132
- return this._delete()
133
- default:
134
- throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
135
- }
136
- }
137
-
138
- private async _store(): Promise<IUser> {
139
- const { lastName, name } = this._args as DtoUser
140
-
141
- try {
142
- const newUser = new UserModel({ lastName, name })
143
- const result = await newUser.save()
144
-
145
- return result
146
- } catch (e) {
147
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
148
- }
149
- }
150
-
151
- private async _getAll(): Promise<IUser[]> {
152
- try {
153
- const users = await UserModel.find({})
154
-
155
- return users
156
- } catch (e) {
157
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
158
- }
159
- }
160
-
161
- private async _deleteAll(): Promise<string> {
162
- try {
163
- const usersDeleted = await UserModel.deleteMany({})
164
-
165
- if (usersDeleted.deletedCount >= 1) return MFU.ALL_USERS_DELETED
166
-
167
- if (usersDeleted.deletedCount === 0)
168
- throw new httpErrors.BadRequest(EFU.NOTHING_TO_DELETE)
169
-
170
- throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
171
- } catch (e) {
172
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
173
- }
174
- }
175
-
176
- private async _getOne(): Promise<IUser> {
177
- const { id } = this._args as DtoUser
178
-
179
- try {
180
- const user = await UserModel.findById(id)
181
-
182
- if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
183
-
184
- return user
185
- } catch (e) {
186
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
187
- }
85
+ interface CustomRequest extends ExpressRequest {
86
+ body: {
87
+ args?: DtoUser
188
88
  }
189
-
190
- private async _update(): Promise<IUser> {
191
- const { id, lastName, name } = this._args as DtoUser
192
-
193
- try {
194
- const updatedUser = await UserModel.findByIdAndUpdate(
195
- id,
196
- { lastName, name },
197
- { new: true }
198
- )
199
-
200
- if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
201
-
202
- return updatedUser
203
- } catch (e) {
204
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
205
- }
206
- }
207
-
208
- private async _delete(): Promise<string> {
209
- const { id } = this._args as DtoUser
210
-
211
- try {
212
- const deletedUser = await UserModel.findByIdAndRemove(id)
213
-
214
- if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
215
-
216
- return MFU.USER_DELETED
217
- } catch (e) {
218
- return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
219
- }
89
+ // We can add custom headers via intersection, remember that for some reason
90
+ // headers must be in Snake-Pascal-Case
91
+ headers: import('http').IncomingHttpHeaders & {
92
+ 'Custom-Header'?: string
220
93
  }
221
94
  }
222
-
223
- export { User }
224
95
  `,
225
- file: `${projectName}/src/controllers/user.ts`
226
- }
227
- },
228
- 'controllers/utils': {
229
- index: {
230
- content: `import httpErrors from 'http-errors'
231
-
232
- import { EFU, MFU, GE } from './messages'
233
-
234
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
235
- const errorHandling = (e: any, message?: string): never => {
236
- console.error(e)
237
-
238
- if (e instanceof httpErrors.HttpError) throw e
96
+ file: `${projectName}/src/@types/custom/request.d.ts`
97
+ },
98
+ response: {
99
+ content: `type ExpressResponse = import('express').Response
239
100
 
240
- throw new httpErrors.InternalServerError(message ?? e.message)
101
+ interface CustomResponse extends ExpressResponse {
102
+ newValue?: string
241
103
  }
242
-
243
- export { EFU, MFU, GE, errorHandling }
244
104
  `,
245
- file: `${projectName}/src/controllers/utils/index.ts`
105
+ file: `${projectName}/src/@types/custom/response.d.ts`
246
106
  }
247
107
  },
248
- 'controllers/utils/messages': {
249
- index: {
250
- content: `import { EFU, MFU } from './user'
251
-
252
- enum GenericErrors {
253
- INTERNAL_SERVER_ERROR = 'Something went wrong'
254
- }
255
-
256
- export { EFU, MFU, GenericErrors as GE }
257
- `,
258
- file: `${projectName}/src/controllers/utils/messages/index.ts`
259
- },
108
+ '@types/models': {
260
109
  user: {
261
- content: `enum ErrorForUser {
262
- NOT_FOUND = 'The requested user does not exists',
263
- NOTHING_TO_DELETE = 'There is no user to be deleted'
264
- }
265
-
266
- enum MessageForUser {
267
- ALL_USERS_DELETED = 'All the users were deleted successfully',
268
- USER_DELETED = 'The requested user was successfully deleted'
110
+ content: `interface IUser {
111
+ _id: import('mongoose').Types.ObjectId
112
+ name: string
113
+ lastName: string
114
+ updatedAt: Date
269
115
  }
270
-
271
- export { ErrorForUser as EFU, MessageForUser as MFU }
272
116
  `,
273
- file: `${projectName}/src/controllers/utils/messages/user.ts`
117
+ file: `${projectName}/src/@types/models/user.d.ts`
274
118
  }
275
119
  },
276
- 'dto-interfaces': {
120
+ database: {
277
121
  index: {
278
- content: `import { DtoUser } from './user'
279
-
280
- export { DtoUser }
281
- `,
282
- file: `${projectName}/src/dto-interfaces/index.ts`
283
- },
284
- user: {
285
- content: `interface DtoUser {
286
- id: string
287
- lastName?: string
288
- name?: string
289
- }
290
-
291
- export { DtoUser }
292
- `,
293
- file: `${projectName}/src/dto-interfaces/user.ts`
122
+ content: "export * from './mongo'\n",
123
+ file: `${projectName}/src/database/index.ts`
294
124
  }
295
125
  },
296
- models: {
126
+ 'database/mongo': {
297
127
  index: {
298
- content: `import { IUser, UserModel } from './user'
299
-
300
- export { IUser, UserModel }
128
+ content: `export * from './models'
129
+ export * from './queries'
301
130
  `,
302
- file: `${projectName}/src/models/index.ts`
131
+ file: `${projectName}/src/database/mongo/index.ts`
132
+ }
133
+ },
134
+ 'database/mongo/models': {
135
+ index: {
136
+ content: "export * from './user'\n",
137
+ file: `${projectName}/src/database/mongo/models/index.ts`
303
138
  },
304
139
  user: {
305
- content: `/* eslint-disable no-underscore-dangle */
306
- import { Document, model, Schema } from 'mongoose'
140
+ content: `import { model, Schema } from 'mongoose'
307
141
 
308
- interface IUser extends Document {
309
- lastName: string
310
- name: string
311
- updatedAt: Date
312
- }
313
-
314
- const User = new Schema(
142
+ const User = new Schema<IUser>(
315
143
  {
316
144
  lastName: {
317
145
  required: true,
@@ -326,36 +154,98 @@ const User = new Schema(
326
154
  timestamps: {
327
155
  createdAt: false,
328
156
  updatedAt: true
157
+ },
158
+ toJSON: {
159
+ transform(_, ret) {
160
+ ret.id = ret._id
161
+ delete ret._id
162
+ delete ret.__v
163
+ delete ret.updatedAt
164
+ },
165
+ versionKey: false,
166
+ virtuals: true
329
167
  }
330
168
  }
331
169
  )
332
170
 
333
- User.set('toJSON', {
334
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
335
- transform: function (_: any, ret: any) {
336
- ret.id = ret._id
337
- delete ret._id
338
- delete ret.__v
339
- delete ret.updatedAt
340
- },
341
- versionKey: false,
342
- virtuals: true
343
- })
344
-
345
171
  const UserModel = model<IUser>('users', User)
346
172
 
347
- export { IUser, UserModel }
173
+ export { UserModel }
174
+ `,
175
+ file: `${projectName}/src/database/mongo/models/user.ts`
176
+ }
177
+ },
178
+ 'database/mongo/queries': {
179
+ index: {
180
+ content: "export * from './user'\n",
181
+ file: `${projectName}/src/database/mongo/queries/index.ts`
182
+ },
183
+ user: {
184
+ content: `import { UserModel } from '../models'
185
+
186
+ const store = async (userData: DtoUser): Promise<IUser> => {
187
+ const user = new UserModel(userData)
188
+
189
+ return await user.save()
190
+ }
191
+
192
+ const remove = async (
193
+ id: string | null = null
194
+ ): Promise<IUser | number | null> => {
195
+ if (id) return await UserModel.findByIdAndRemove(id)
196
+
197
+ return (await UserModel.deleteMany({})).deletedCount
198
+ }
199
+
200
+ const get = async (
201
+ id: string | null = null
202
+ ): Promise<IUser[] | IUser | null> => {
203
+ if (id) return await UserModel.findById(id)
204
+
205
+ return await UserModel.find({})
206
+ }
207
+
208
+ const update = async (userData: DtoUser): Promise<IUser | null> => {
209
+ const { id, ...rest } = userData
210
+
211
+ return await UserModel.findByIdAndUpdate(id, rest, { new: true })
212
+ }
213
+
214
+ export { store, remove, get, update }
348
215
  `,
349
- file: `${projectName}/src/models/user.ts`
216
+ file: `${projectName}/src/database/mongo/queries/user.ts`
350
217
  }
351
218
  },
352
219
  network: {
353
- routes: {
220
+ index: {
221
+ content: `export * from './routes'
222
+ export * from './server'
223
+ `,
224
+ file: `${projectName}/src/network/index.ts`
225
+ },
226
+ response: {
227
+ content: `interface ResponseProps {
228
+ error: boolean
229
+ message: unknown
230
+ res: CustomResponse
231
+ status: number
232
+ }
233
+
234
+ const response = ({ error, message, res, status }: ResponseProps): void => {
235
+ res.status(status).send({ error, message })
236
+ }
237
+
238
+ export { response }
239
+ `,
240
+ file: `${projectName}/src/network/response.ts`
241
+ },
242
+ router: {
354
243
  content: `import { Application, Response, Request, Router, NextFunction } from 'express'
355
244
  import swaggerUi from 'swagger-ui-express'
356
245
  import httpErrors from 'http-errors'
357
246
 
358
- import { Home, User } from 'routes'
247
+ import { response } from './response'
248
+ import { Home, User } from './routes'
359
249
  import { docs } from 'utils'
360
250
 
361
251
  const routers = [User]
@@ -389,14 +279,14 @@ const applyRoutes = (app: Application): void => {
389
279
 
390
280
  export { applyRoutes }
391
281
  `,
392
- file: `${projectName}/src/network/routes.ts`
282
+ file: `${projectName}/src/network/router.ts`
393
283
  },
394
284
  server: {
395
285
  content: `import express from 'express'
396
286
  import mongoose from 'mongoose'
397
287
  import morgan from 'morgan'
398
288
 
399
- import { applyRoutes } from './routes'
289
+ import { applyRoutes } from './router'
400
290
 
401
291
  const PORT = (process.env.PORT as string) || '1996'
402
292
 
@@ -430,16 +320,6 @@ class Server {
430
320
  }
431
321
  )
432
322
 
433
- // setting up the global response
434
- global.response = ({
435
- error,
436
- message,
437
- res,
438
- status
439
- }: ResponseProps): void => {
440
- res.status(status).send({ error, message })
441
- }
442
-
443
323
  applyRoutes(this._app)
444
324
  }
445
325
 
@@ -495,20 +375,14 @@ const server = new Server()
495
375
  export { server as Server }
496
376
  `,
497
377
  file: `${projectName}/src/network/server.ts`
498
- },
499
- index: {
500
- content: `import { applyRoutes } from './routes'
501
- import { Server } from './server'
502
-
503
- export { applyRoutes, Server }
504
- `,
505
- file: `${projectName}/src/network/index.ts`
506
378
  }
507
379
  },
508
- routes: {
380
+ 'network/routes': {
509
381
  home: {
510
382
  content: `import { Response, Request, Router } from 'express'
511
383
 
384
+ import { response } from 'network/response'
385
+
512
386
  const Home = Router()
513
387
 
514
388
  Home.route('').get((req: Request, res: Response) => {
@@ -522,24 +396,22 @@ Home.route('').get((req: Request, res: Response) => {
522
396
 
523
397
  export { Home }
524
398
  `,
525
- file: `${projectName}/src/routes/home.ts`
399
+ file: `${projectName}/src/network/routes/home.ts`
526
400
  },
527
401
  index: {
528
- content: `import { Home } from './home'
529
- import { User } from './user'
530
-
531
- export { Home, User }
402
+ content: `export * from './home'
403
+ export * from './user'
532
404
  `,
533
- file: `${projectName}/src/routes/index.ts`
405
+ file: `${projectName}/src/network/routes/index.ts`
534
406
  },
535
407
  user: {
536
408
  content: `import { Router, NextFunction } from 'express'
537
409
  import httpErrors from 'http-errors'
538
410
  import { ValidationError } from 'joi'
539
411
 
540
- import { User as UserC } from 'controllers/user'
541
- import { DtoUser } from 'dto-interfaces'
542
- import { idSchema, userSchema } from 'schemas'
412
+ import { response } from 'network/response'
413
+ import { UserService } from 'services/user'
414
+ import { idSchema, userSchema } from './schemas'
543
415
 
544
416
  const User = Router()
545
417
 
@@ -553,10 +425,10 @@ User.route('/users')
553
425
  const {
554
426
  body: { args }
555
427
  } = req
556
- const u = new UserC(args as DtoUser)
428
+ const us = new UserService(args as DtoUser)
557
429
 
558
430
  try {
559
- const result = await u.process({ type: 'store' })
431
+ const result = await us.process({ type: 'store' })
560
432
  response({ error: false, message: result, res, status: 201 })
561
433
  } catch (e) {
562
434
  next(e)
@@ -569,10 +441,10 @@ User.route('/users')
569
441
  res: CustomResponse,
570
442
  next: NextFunction
571
443
  ): Promise<void> => {
572
- const u = new UserC()
444
+ const us = new UserService()
573
445
 
574
446
  try {
575
- const result = await u.process({ type: 'getAll' })
447
+ const result = await us.process({ type: 'getAll' })
576
448
  response({ error: false, message: result, res, status: 200 })
577
449
  } catch (e) {
578
450
  next(e)
@@ -585,10 +457,10 @@ User.route('/users')
585
457
  res: CustomResponse,
586
458
  next: NextFunction
587
459
  ): Promise<void> => {
588
- const u = new UserC()
460
+ const us = new UserService()
589
461
 
590
462
  try {
591
- const result = await u.process({ type: 'deleteAll' })
463
+ const result = await us.process({ type: 'deleteAll' })
592
464
  response({ error: false, message: result, res, status: 200 })
593
465
  } catch (e) {
594
466
  next(e)
@@ -609,8 +481,8 @@ User.route('/user/:id')
609
481
 
610
482
  try {
611
483
  await idSchema.validateAsync(id)
612
- const u = new UserC({ id } as DtoUser)
613
- const result = await u.process({ type: 'getOne' })
484
+ const us = new UserService({ id } as DtoUser)
485
+ const result = await us.process({ type: 'getOne' })
614
486
  response({ error: false, message: result, res, status: 200 })
615
487
  } catch (e) {
616
488
  if (e instanceof ValidationError)
@@ -637,8 +509,8 @@ User.route('/user/:id')
637
509
 
638
510
  try {
639
511
  await userSchema.validateAsync(user)
640
- const u = new UserC(user)
641
- const result = await u.process({ type: 'update' })
512
+ const us = new UserService(user)
513
+ const result = await us.process({ type: 'update' })
642
514
  response({ error: false, message: result, res, status: 200 })
643
515
  } catch (e) {
644
516
  if (e instanceof ValidationError)
@@ -660,8 +532,8 @@ User.route('/user/:id')
660
532
 
661
533
  try {
662
534
  await idSchema.validateAsync(id)
663
- const u = new UserC({ id } as DtoUser)
664
- const result = await u.process({ type: 'delete' })
535
+ const us = new UserService({ id } as DtoUser)
536
+ const result = await us.process({ type: 'delete' })
665
537
  response({ error: false, message: result, res, status: 200 })
666
538
  } catch (e) {
667
539
  if (e instanceof ValidationError)
@@ -674,20 +546,19 @@ User.route('/user/:id')
674
546
 
675
547
  export { User }
676
548
  `,
677
- file: `${projectName}/src/routes/user.ts`
549
+ file: `${projectName}/src/network/routes/user.ts`
678
550
  }
679
551
  },
680
- schemas: {
552
+ 'network/routes/schemas': {
681
553
  index: {
682
554
  content: `import Joi from 'joi'
683
555
 
684
- import { userSchema } from './user'
685
-
686
556
  const idSchema = Joi.string().length(24).required()
687
557
 
688
- export { idSchema, userSchema }
558
+ export { idSchema }
559
+ export * from './user'
689
560
  `,
690
- file: `${projectName}/src/schemas/index.ts`
561
+ file: `${projectName}/src/network/routes/schemas/index.ts`
691
562
  },
692
563
  user: {
693
564
  content: `import Joi from 'joi'
@@ -700,7 +571,175 @@ const userSchema = Joi.object().keys({
700
571
 
701
572
  export { userSchema }
702
573
  `,
703
- file: `${projectName}/src/schemas/user.ts`
574
+ file: `${projectName}/src/network/routes/schemas/user.ts`
575
+ }
576
+ },
577
+ services: {
578
+ index: {
579
+ content: "export * from './user'\n",
580
+ file: `${projectName}/src/services/index.ts`
581
+ },
582
+ user: {
583
+ content: `import httpErrors from 'http-errors'
584
+
585
+ import { store, remove, get, update } from 'database'
586
+ import { EFU, MFU, GE, errorHandling } from './utils'
587
+
588
+ type Process = {
589
+ type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
590
+ }
591
+
592
+ class UserService {
593
+ private _args: DtoUser | null
594
+
595
+ constructor(args: DtoUser | null = null) {
596
+ this._args = args
597
+ }
598
+
599
+ public process({ type }: Process): Promise<string | IUser[] | IUser> {
600
+ switch (type) {
601
+ case 'store':
602
+ return this._store()
603
+ case 'getAll':
604
+ return this._getAll()
605
+ case 'deleteAll':
606
+ return this._deleteAll()
607
+ case 'getOne':
608
+ return this._getOne()
609
+ case 'update':
610
+ return this._update()
611
+ case 'delete':
612
+ return this._delete()
613
+ default:
614
+ throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
615
+ }
616
+ }
617
+
618
+ private async _store(): Promise<IUser> {
619
+ try {
620
+ const result = await store(this._args as DtoUser)
621
+
622
+ return result
623
+ } catch (e) {
624
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
625
+ }
626
+ }
627
+
628
+ private async _getAll(): Promise<IUser[]> {
629
+ try {
630
+ const users = (await get()) as IUser[]
631
+
632
+ return users
633
+ } catch (e) {
634
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
635
+ }
636
+ }
637
+
638
+ private async _deleteAll(): Promise<string> {
639
+ try {
640
+ const usersDeleted = (await remove()) as number
641
+
642
+ if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
643
+
644
+ if (usersDeleted === 0)
645
+ throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
646
+
647
+ throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
648
+ } catch (e) {
649
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
650
+ }
651
+ }
652
+
653
+ private async _getOne(): Promise<IUser> {
654
+ const { id } = this._args as DtoUser
655
+
656
+ try {
657
+ const user = (await get(id as string)) as IUser | null
658
+
659
+ if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
660
+
661
+ return user
662
+ } catch (e) {
663
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
664
+ }
665
+ }
666
+
667
+ private async _update(): Promise<IUser> {
668
+ try {
669
+ const updatedUser = await update(this._args as DtoUser)
670
+
671
+ if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
672
+
673
+ return updatedUser
674
+ } catch (e) {
675
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
676
+ }
677
+ }
678
+
679
+ private async _delete(): Promise<string> {
680
+ const { id } = this._args as DtoUser
681
+
682
+ try {
683
+ const deletedUser = await remove(id)
684
+
685
+ if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
686
+
687
+ return MFU.USER_DELETED
688
+ } catch (e) {
689
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
690
+ }
691
+ }
692
+ }
693
+
694
+ export { UserService }
695
+ `,
696
+ file: `${projectName}/src/services/user.ts`
697
+ }
698
+ },
699
+ 'services/utils': {
700
+ index: {
701
+ content: `import httpErrors from 'http-errors'
702
+
703
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
704
+ const errorHandling = (e: any, message?: string): never => {
705
+ console.error(e)
706
+
707
+ if (e instanceof httpErrors.HttpError) throw e
708
+
709
+ throw new httpErrors.InternalServerError(message ?? e.message)
710
+ }
711
+
712
+ export { errorHandling }
713
+ export * from './messages'
714
+ `,
715
+ file: `${projectName}/src/services/utils/index.ts`
716
+ }
717
+ },
718
+ 'services/utils/messages': {
719
+ index: {
720
+ content: `enum GenericErrors {
721
+ INTERNAL_SERVER_ERROR = 'Something went wrong'
722
+ }
723
+
724
+ export { GenericErrors as GE }
725
+ export * from './user'
726
+ `,
727
+ file: `${projectName}/src/services/utils/messages/index.ts`
728
+ },
729
+ user: {
730
+ content: `enum ErrorForUser {
731
+ NOT_FOUND = 'The requested user does not exists',
732
+ NOTHING_TO_DELETE = 'There is no user to be deleted'
733
+ }
734
+
735
+ enum MessageForUser {
736
+ ALL_USERS_DELETED = 'All the users were deleted successfully',
737
+ USER_DELETED = 'The requested user was successfully deleted'
738
+ }
739
+
740
+ export { ErrorForUser as EFU, MessageForUser as MFU }
741
+ `,
742
+ file: `${projectName}/src/services/utils/messages/user.ts`
704
743
  }
705
744
  },
706
745
  test: {
@@ -1164,10 +1203,7 @@ DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
1164
1203
  file: `${projectName}/src/utils/docs.json`
1165
1204
  },
1166
1205
  index: {
1167
- content: `import docs from './docs.json'
1168
-
1169
- export { docs }
1170
- `,
1206
+ content: "export { default as docs } from './docs.json'\n",
1171
1207
  file: `${projectName}/src/utils/index.ts`
1172
1208
  }
1173
1209
  },
@@ -1184,70 +1220,123 @@ Server.start()
1184
1220
  }
1185
1221
  }
1186
1222
 
1187
- await exec(`mkdir ${projectName}/src \
1223
+ const createFoldersCommands = `mkdir ${projectName}/src \
1188
1224
  ${projectName}/src/@types \
1189
- ${projectName}/src/controllers \
1190
- ${projectName}/src/controllers/utils \
1191
- ${projectName}/src/controllers/utils/messages \
1192
- ${projectName}/src/dto-interfaces \
1193
- ${projectName}/src/models \
1225
+ ${projectName}/src/@types/dto \
1226
+ ${projectName}/src/@types/custom \
1227
+ ${projectName}/src/@types/models \
1228
+ ${projectName}/src/services \
1229
+ ${projectName}/src/services/utils \
1230
+ ${projectName}/src/services/utils/messages \
1231
+ ${projectName}/src/database \
1232
+ ${projectName}/src/database/mongo \
1233
+ ${projectName}/src/database/mongo/models \
1234
+ ${projectName}/src/database/mongo/queries \
1194
1235
  ${projectName}/src/network \
1195
- ${projectName}/src/routes \
1196
- ${projectName}/src/schemas \
1236
+ ${projectName}/src/network/routes \
1237
+ ${projectName}/src/network/routes/schemas \
1197
1238
  ${projectName}/src/test \
1198
1239
  ${projectName}/src/utils
1199
- `)
1240
+ `
1241
+
1242
+ if (os.platform() === 'win32')
1243
+ await exec(createFoldersCommands.replaceAll('/', '\\'))
1244
+ else await exec(createFoldersCommands)
1200
1245
 
1201
1246
  // /@types
1202
1247
  await writeFile(data['@types'].index.file, data['@types'].index.content)
1203
1248
 
1204
- // /controllers
1205
- await writeFile(data.controllers.user.file, data.controllers.user.content)
1206
- await writeFile(data.controllers.index.file, data.controllers.index.content)
1249
+ // /@types/custom
1250
+ await writeFile(
1251
+ data['@types/custom'].request.file,
1252
+ data['@types/custom'].request.content
1253
+ )
1254
+ await writeFile(
1255
+ data['@types/custom'].response.file,
1256
+ data['@types/custom'].response.content
1257
+ )
1258
+
1259
+ // /@types/dto
1260
+ await writeFile(data['@types/dto'].user.file, data['@types/dto'].user.content)
1207
1261
 
1208
- // /controllers/utils
1262
+ // /@types/models
1209
1263
  await writeFile(
1210
- data['controllers/utils'].index.file,
1211
- data['controllers/utils'].index.content
1264
+ data['@types/models'].user.file,
1265
+ data['@types/models'].user.content
1212
1266
  )
1213
1267
 
1214
- // /controllers/utils/messages
1268
+ // /services
1269
+ await writeFile(data.services.user.file, data.services.user.content)
1270
+ await writeFile(data.services.index.file, data.services.index.content)
1271
+
1272
+ // /database
1273
+ await writeFile(data.database.index.file, data.database.index.content)
1215
1274
  await writeFile(
1216
- data['controllers/utils/messages'].user.file,
1217
- data['controllers/utils/messages'].user.content
1275
+ data['database/mongo'].index.file,
1276
+ data['database/mongo'].index.content
1218
1277
  )
1219
1278
  await writeFile(
1220
- data['controllers/utils/messages'].index.file,
1221
- data['controllers/utils/messages'].index.content
1279
+ data['database/mongo/models'].index.file,
1280
+ data['database/mongo/models'].index.content
1222
1281
  )
1223
-
1224
- // /dto-interfaces
1225
1282
  await writeFile(
1226
- data['dto-interfaces'].user.file,
1227
- data['dto-interfaces'].user.content
1283
+ data['database/mongo/models'].user.file,
1284
+ data['database/mongo/models'].user.content
1228
1285
  )
1229
1286
  await writeFile(
1230
- data['dto-interfaces'].index.file,
1231
- data['dto-interfaces'].index.content
1287
+ data['database/mongo/queries'].index.file,
1288
+ data['database/mongo/queries'].index.content
1289
+ )
1290
+ await writeFile(
1291
+ data['database/mongo/queries'].user.file,
1292
+ data['database/mongo/queries'].user.content
1232
1293
  )
1233
1294
 
1234
- // /models
1235
- await writeFile(data.models.user.file, data.models.user.content)
1236
- await writeFile(data.models.index.file, data.models.index.content)
1295
+ // /services/utils
1296
+ await writeFile(
1297
+ data['services/utils'].index.file,
1298
+ data['services/utils'].index.content
1299
+ )
1300
+
1301
+ // /services/utils/messages
1302
+ await writeFile(
1303
+ data['services/utils/messages'].user.file,
1304
+ data['services/utils/messages'].user.content
1305
+ )
1306
+ await writeFile(
1307
+ data['services/utils/messages'].index.file,
1308
+ data['services/utils/messages'].index.content
1309
+ )
1237
1310
 
1238
1311
  // /network
1239
- await writeFile(data.network.routes.file, data.network.routes.content)
1240
- await writeFile(data.network.server.file, data.network.server.content)
1241
1312
  await writeFile(data.network.index.file, data.network.index.content)
1313
+ await writeFile(data.network.response.file, data.network.response.content)
1314
+ await writeFile(data.network.router.file, data.network.router.content)
1315
+ await writeFile(data.network.server.file, data.network.server.content)
1242
1316
 
1243
- // /routes
1244
- await writeFile(data.routes.home.file, data.routes.home.content)
1245
- await writeFile(data.routes.user.file, data.routes.user.content)
1246
- await writeFile(data.routes.index.file, data.routes.index.content)
1317
+ // /network/routes
1318
+ await writeFile(
1319
+ data['network/routes'].home.file,
1320
+ data['network/routes'].home.content
1321
+ )
1322
+ await writeFile(
1323
+ data['network/routes'].user.file,
1324
+ data['network/routes'].user.content
1325
+ )
1326
+ await writeFile(
1327
+ data['network/routes'].index.file,
1328
+ data['network/routes'].index.content
1329
+ )
1247
1330
 
1248
- // /schemas
1249
- await writeFile(data.schemas.index.file, data.schemas.index.content)
1250
- await writeFile(data.schemas.user.file, data.schemas.user.content)
1331
+ // /network/routes/schemas
1332
+ await writeFile(
1333
+ data['network/routes/schemas'].index.file,
1334
+ data['network/routes/schemas'].index.content
1335
+ )
1336
+ await writeFile(
1337
+ data['network/routes/schemas'].user.file,
1338
+ data['network/routes/schemas'].user.content
1339
+ )
1251
1340
 
1252
1341
  // /test
1253
1342
  await writeFile(data.test.index.file, data.test.index.content)
@@ -6,7 +6,8 @@ const writeFile = require('../utils/writeFile')
6
6
  */
7
7
  module.exports = async projectName => {
8
8
  const data = {
9
- tsconfigContent: `{
9
+ base: {
10
+ content: `{
10
11
  "ts-node": {
11
12
  "files": true,
12
13
  "require": ["tsconfig-paths/register"]
@@ -25,8 +26,8 @@ module.exports = async projectName => {
25
26
  // "declaration": true, /* Generates corresponding '.d.ts' file. */
26
27
  // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
27
28
  // "outFile": "./", /* Concatenate and emit output to single file. */
28
- "outDir": "./dist/" /* Redirect output structure to the directory. */,
29
- "rootDir": "./src/" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
29
+ "outDir": "dist" /* Redirect output structure to the directory. */,
30
+ "rootDir": "src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
30
31
  // "composite": true, /* Enable project compilation */
31
32
  // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
32
33
  // "removeComments": true, /* Do not emit comments to output. */
@@ -53,7 +54,7 @@ module.exports = async projectName => {
53
54
 
54
55
  /* Module Resolution Options */
55
56
  "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
56
- "baseUrl": "./src", /* Base directory to resolve non-absolute module names. */
57
+ "baseUrl": "src", /* Base directory to resolve non-absolute module names. */
57
58
  // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
58
59
  // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
59
60
  // "typeRoots": [], /* List of folders to include type definitions from. */
@@ -79,12 +80,41 @@ module.exports = async projectName => {
79
80
  "skipLibCheck": true /* Skip type checking of declaration files. */,
80
81
  "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
81
82
  },
82
- "include": ["./src/"],
83
- "exclude": ["node_modules", "**/*.test.ts"]
83
+ "include": [
84
+ "src",
85
+ "test",
86
+ "tests",
87
+ "__test__"
88
+ ],
89
+ "exclude": [
90
+ "node_modules"
91
+ ]
84
92
  }
85
93
  `,
86
- tsconfigFile: 'tsconfig.json'
94
+ file: 'tsconfig.base.json'
95
+ },
96
+ prod: {
97
+ content: `{
98
+ "compilerOptions": {
99
+ "rootDir": "src"
100
+ },
101
+ "extends": "./tsconfig.base.json",
102
+ "exclude": [
103
+ "node_modules",
104
+ "test",
105
+ "tests",
106
+ "__test__",
107
+ "dist"
108
+ ],
109
+ "include": [
110
+ "src"
111
+ ]
112
+ }
113
+ `,
114
+ file: 'tsconfig.json'
115
+ }
87
116
  }
88
117
 
89
- await writeFile(`${projectName}/${data.tsconfigFile}`, data.tsconfigContent)
118
+ await writeFile(`${projectName}/${data.base.file}`, data.base.content)
119
+ await writeFile(`${projectName}/${data.prod.file}`, data.prod.content)
90
120
  }
@@ -56,7 +56,7 @@ module.exports = async ({
56
56
  cliProgress.Presets.shades_classic
57
57
  )
58
58
 
59
- const prodPackages = `${manager} express mongoose morgan http-errors joi swagger-ui-express`
59
+ const prodPackages = `${manager} express http-errors joi mongoose morgan swagger-ui-express`
60
60
  const devPackages = `${manager} -D \
61
61
  @types/express \
62
62
  @types/http-errors \
@@ -71,8 +71,6 @@ eslint-config-prettier \
71
71
  eslint-config-standard \
72
72
  eslint-plugin-import \
73
73
  eslint-plugin-prettier \
74
- eslint-plugin-sort-keys-fix \
75
- eslint-plugin-typescript-sort-keys \
76
74
  nodemon \
77
75
  prettier \
78
76
  standard-version \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anthonylzq/simba.js",
3
- "version": "1.10.0",
3
+ "version": "2.0.3",
4
4
  "description": "set up a modern backend app by running one command",
5
5
  "main": "lib/index.js",
6
6
  "directories": {