@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 +1 -0
- package/lib/index.js +42 -4
- package/lib/src/functions/api/database.js +133 -10
- package/lib/src/functions/api/index.js +4 -2
- package/lib/src/functions/api/network.js +71 -176
- package/lib/src/functions/eslint.js +40 -12
- package/lib/src/functions/ghat.js +65 -0
- package/lib/src/functions/gitignore.js +1 -0
- package/lib/src/functions/packageJson.js +11 -2
- package/lib/src/functions/tests.js +615 -0
- package/lib/src/index.js +23 -12
- package/lib/src/utils/constants.js +3 -0
- package/package.json +26 -15
package/README.md
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
[](https://standardjs.com)
|
|
9
9
|
[](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
|
|
10
10
|
[](https://github.com/AnthonyLzq/simba.js/actions/workflows/lint.yml)
|
|
11
|
+
[](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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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
|
-
|
|
272
|
+
writeFile(
|
|
151
273
|
database.mongo.models.user.file,
|
|
152
274
|
database.mongo.models.user.content
|
|
153
275
|
),
|
|
154
|
-
|
|
276
|
+
writeFile(
|
|
155
277
|
database.mongo.queries.index.file,
|
|
156
278
|
database.mongo.queries.index.content
|
|
157
279
|
),
|
|
158
|
-
|
|
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.
|
|
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({
|