@anthonylzq/simba.js 5.2.0 → 6.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
@@ -8,6 +8,7 @@
8
8
  [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
9
9
  [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
10
10
  [![Lint](https://github.com/AnthonyLzq/simba.js/actions/workflows/lint.yml/badge.svg)](https://github.com/AnthonyLzq/simba.js/actions/workflows/lint.yml)
11
+ [![Tests for Simba APIs](https://github.com/AnthonyLzq/simba.js/actions/workflows/test.yml/badge.svg)](https://github.com/AnthonyLzq/simba.js/actions/workflows/test.yml)
11
12
 
12
13
  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.
13
14
 
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 -q" 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 -l mit -F --tests --ghat"
16
16
  )
17
17
  .alias('N', 'projectName')
18
18
  .nargs('N', 1)
@@ -54,6 +54,16 @@ const argv = yargs(hideBin(process.argv))
54
54
  .describe('F', 'Whether or not you want to use Fastify for your project')
55
55
  .alias('g', 'graphql')
56
56
  .describe('g', 'Whether or not you want to use GraphQL for your project')
57
+ .alias('t', 'tests')
58
+ .describe(
59
+ 't',
60
+ 'Whether or not you want to have a basic suit of unit tests with Jest'
61
+ )
62
+ .alias('ghat', 'gh-action-tests')
63
+ .describe(
64
+ 'ghat',
65
+ 'Whether or not you want to have a GitHub Action with a CI for your tests. If this option is set to true, the tests flag must be set to true.'
66
+ )
57
67
  .default({
58
68
  H: false,
59
69
  n: false,
@@ -63,9 +73,11 @@ const argv = yargs(hideBin(process.argv))
63
73
  f: 'src/index.ts',
64
74
  q: false,
65
75
  F: false,
66
- g: false
76
+ g: false,
77
+ t: false,
78
+ ghat: false
67
79
  })
68
- .boolean(['H', 'n', 'q', 'F', 'g'])
80
+ .boolean(['H', 'n', 'q', 'F', 'g', 't'])
69
81
  .help('h')
70
82
  .alias('h', 'help')
71
83
  .epilog('Developed by AnthonyLzq').argv
@@ -84,7 +96,9 @@ const config = {
84
96
  manager: 'yarn add',
85
97
  mainFile: 'src/index.ts',
86
98
  fastify: false,
87
- graphql: false
99
+ graphql: false,
100
+ tests: true,
101
+ ghat: true
88
102
  }
89
103
  const UNLICENSED = 'unlicensed'
90
104
  const LICENSES = [
@@ -216,6 +230,21 @@ const main = async () => {
216
230
  }
217
231
  )
218
232
  config.mainFile = readLineSync.question('> Main file (src/index.ts): ')
233
+ config.tests = readLineSync.keyInYNStrict(
234
+ '> Would you want to have a basic suit of tests with Jest? ',
235
+ {
236
+ caseSensitive: false
237
+ }
238
+ )
239
+
240
+ if (config.tests)
241
+ config.ghat = readLineSync.keyInYNStrict(
242
+ '> Would you want to have a basic GitHub Action for the suit of tests?',
243
+ {
244
+ caseSensitive: false
245
+ }
246
+ )
247
+ else config.ghat = false
219
248
  } else {
220
249
  if (!argv.author) return console.log('Error! An author is required!')
221
250
  else config.author = argv.author
@@ -289,6 +318,15 @@ const main = async () => {
289
318
 
290
319
  if (!argv.mainFile) console.log('Using src/index.ts as default main file')
291
320
  else config.mainFile = argv.mainFile
321
+
322
+ if (argv.tests) config.tests = true
323
+
324
+ if (argv.ghat) config.ghat = true
325
+
326
+ if (!config.tests && argv.ghat)
327
+ return console.log(
328
+ 'GitHub Action for tests can not be set to true if the tests flag is set to false'
329
+ )
292
330
  }
293
331
 
294
332
  await installation(config)
@@ -5,9 +5,10 @@ const writeFile = require('../../utils/writeFile')
5
5
 
6
6
  /**
7
7
  * @param {Object} args
8
- * @param {String} projectName
8
+ * @param {String} args.projectName
9
+ * @param {Boolean} args.fastify
9
10
  */
10
- const mongoF = async ({ projectName }) => {
11
+ const mongoF = async ({ projectName, fastify }) => {
11
12
  const createFoldersCommand = `mkdir ${projectName}/src/database/mongo \
12
13
  ${projectName}/src/database/mongo/models \
13
14
  ${projectName}/src/database/mongo/queries`
@@ -22,9 +23,126 @@ ${projectName}/src/database/mongo/queries`
22
23
  file: `${projectName}/src/database/index.ts`
23
24
  },
24
25
  mongo: {
26
+ connection: {
27
+ content: fastify
28
+ ? `import { connect, connection } from 'mongoose'
29
+ import { FastifyLoggerInstance } from 'fastify'
30
+
31
+ const ENVIRONMENTS_WITHOUT_RECONNECTION = ['ci', 'local']
32
+ const dbConnection = async (
33
+ logger: FastifyLoggerInstance
34
+ ): Promise<{
35
+ connect: () => Promise<typeof import('mongoose')>
36
+ disconnect: () => Promise<void>
37
+ }> => {
38
+ const connectionConfig = {
39
+ keepAlive: true,
40
+ useNewUrlParser: true,
41
+ useUnifiedTopology: true
42
+ }
43
+
44
+ connection.on('connected', () => {
45
+ logger.info('Mongo connection established.')
46
+ })
47
+ connection.on('reconnected', () => {
48
+ logger.info('Mongo connection reestablished')
49
+ })
50
+ connection.on('disconnected', () => {
51
+ if (
52
+ !ENVIRONMENTS_WITHOUT_RECONNECTION.includes(
53
+ process.env.NODE_ENV as string
54
+ )
55
+ ) {
56
+ logger.info(
57
+ 'Mongo connection disconnected. Trying to reconnected to Mongo...'
58
+ )
59
+ setTimeout(() => {
60
+ connect(process.env.MONGO_URI as string, {
61
+ ...connection,
62
+ connectTimeoutMS: 3000,
63
+ socketTimeoutMS: 3000
64
+ })
65
+ }, 3000)
66
+ }
67
+ })
68
+ connection.on('close', () => {
69
+ logger.info('Mongo connection closed')
70
+ })
71
+ connection.on('error', (e: Error) => {
72
+ logger.info('Mongo connection error:')
73
+ logger.error(e)
74
+ })
75
+
76
+ return {
77
+ connect: () => connect(process.env.MONGO_URI as string, connectionConfig),
78
+ disconnect: () => connection.close()
79
+ }
80
+ }
81
+
82
+ export { dbConnection }
83
+ `
84
+ : `import { connect, connection } from 'mongoose'
85
+ import { HttpLogger } from 'express-pino-logger'
86
+
87
+ const ENVIRONMENTS_WITHOUT_RECONNECTION = ['ci', 'local']
88
+ const dbConnection = async (
89
+ logger: HttpLogger['logger']
90
+ ): Promise<{
91
+ connect: () => Promise<typeof import('mongoose')>
92
+ disconnect: () => Promise<void>
93
+ }> => {
94
+ const connectionConfig = {
95
+ keepAlive: true,
96
+ useNewUrlParser: true,
97
+ useUnifiedTopology: true
98
+ }
99
+
100
+ connection.on('connected', () => {
101
+ logger.info('Mongo connection established.')
102
+ })
103
+ connection.on('reconnected', () => {
104
+ logger.info('Mongo connection reestablished')
105
+ })
106
+ connection.on('disconnected', () => {
107
+ if (
108
+ !ENVIRONMENTS_WITHOUT_RECONNECTION.includes(
109
+ process.env.NODE_ENV as string
110
+ )
111
+ ) {
112
+ logger.info(
113
+ 'Mongo connection disconnected. Trying to reconnected to Mongo...'
114
+ )
115
+ setTimeout(() => {
116
+ connect(process.env.MONGO_URI as string, {
117
+ ...connection,
118
+ connectTimeoutMS: 3000,
119
+ socketTimeoutMS: 3000
120
+ })
121
+ }, 3000)
122
+ }
123
+ })
124
+ connection.on('close', () => {
125
+ logger.info('Mongo connection closed')
126
+ })
127
+ connection.on('error', (e: Error) => {
128
+ logger.info('Mongo connection error:')
129
+ logger.error(e)
130
+ })
131
+
132
+ return {
133
+ connect: () => connect(process.env.MONGO_URI as string, connectionConfig),
134
+ disconnect: () => connection.close()
135
+ }
136
+ }
137
+
138
+ export { dbConnection }
139
+ `,
140
+ file: `${projectName}/src/database/mongo/connection.ts`
141
+ },
25
142
  index: {
26
143
  content: `export * from './models'
27
144
  export * from './queries'
145
+ export * from './connection'
28
146
  `,
29
147
  file: `${projectName}/src/database/mongo/index.ts`
30
148
  },
@@ -141,21 +259,25 @@ export { store, remove, get, update }
141
259
  }
142
260
 
143
261
  await Promise.all([
144
- await writeFile(database.index.file, database.index.content),
145
- await writeFile(database.mongo.index.file, database.mongo.index.content),
146
- await writeFile(
262
+ writeFile(database.index.file, database.index.content),
263
+ writeFile(
264
+ database.mongo.connection.file,
265
+ database.mongo.connection.content
266
+ ),
267
+ writeFile(database.mongo.index.file, database.mongo.index.content),
268
+ writeFile(
147
269
  database.mongo.models.index.file,
148
270
  database.mongo.models.index.content
149
271
  ),
150
- await writeFile(
272
+ writeFile(
151
273
  database.mongo.models.user.file,
152
274
  database.mongo.models.user.content
153
275
  ),
154
- await writeFile(
276
+ writeFile(
155
277
  database.mongo.queries.index.file,
156
278
  database.mongo.queries.index.content
157
279
  ),
158
- await writeFile(
280
+ writeFile(
159
281
  database.mongo.queries.user.file,
160
282
  database.mongo.queries.user.content
161
283
  )
@@ -166,13 +288,14 @@ export { store, remove, get, update }
166
288
  * @param {Object} args
167
289
  * @param {Boolean|undefined} args.mongo
168
290
  * @param {String} args.projectName
291
+ * @param {Boolean} args.fastify
169
292
  */
170
- module.exports = async ({ mongo = true, projectName }) => {
293
+ module.exports = async ({ mongo = true, projectName, fastify }) => {
171
294
  const createFoldersCommand = `mkdir ${projectName}/src/database`
172
295
 
173
296
  if (platform() === 'win32')
174
297
  await exec(createFoldersCommand.replaceAll('/', '\\'))
175
298
  else await exec(createFoldersCommand)
176
299
 
177
- if (mongo) await mongoF({ projectName })
300
+ if (mongo) await mongoF({ projectName, fastify })
178
301
  }
@@ -9,6 +9,7 @@ const types = require('./types')
9
9
  const network = require('./network')
10
10
  const utils = require('./utils')
11
11
  const writeFile = require('../../utils/writeFile')
12
+ const { ENVIRONMENTS_WITH_MONGO_URI } = require('../../utils/constants')
12
13
 
13
14
  /*
14
15
  * Express api:
@@ -163,7 +164,7 @@ DELETE http://localhost:1996/api/user/60e7e3b93b01c1a7aa74cd6b
163
164
  },
164
165
  '.env': {
165
166
  content: `MONGO_URI = ${
166
- process.env.LOCAL
167
+ ENVIRONMENTS_WITH_MONGO_URI.includes(process.env.NODE_ENV)
167
168
  ? process.env.MONGO_URI
168
169
  : `mongodb://mongo:mongo@mongo:27017/${projectName}`
169
170
  }`,
@@ -194,7 +195,8 @@ Server.start()
194
195
  // /database
195
196
  database({
196
197
  mongo,
197
- projectName
198
+ projectName,
199
+ fastify
198
200
  }),
199
201
  // /network
200
202
  network({