@anthonylzq/simba.js 7.2.0 → 8.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.
@@ -3,299 +3,260 @@ const { promisify } = require('util')
3
3
  const exec = promisify(require('child_process').exec)
4
4
  const writeFile = require('../../utils/writeFile')
5
5
 
6
+ const dbPrismaName = {
7
+ postgres: 'postgresql',
8
+ mysql: 'mysql',
9
+ mariadb: 'mysql',
10
+ sqlite: 'sqlite',
11
+ sqlServer: 'sqlserver',
12
+ mongo: 'mongodb'
13
+ }
14
+
15
+ const dbPrettyName = {
16
+ postgres: 'PostgreSQL',
17
+ mysql: 'MySQL',
18
+ mariadb: 'MariaDB',
19
+ sqlite: 'SQLite',
20
+ sqlServer: 'SQL Server',
21
+ mongo: 'MongoDB'
22
+ }
23
+
6
24
  /**
7
25
  * @param {Object} args
8
26
  * @param {String} args.projectName
9
- * @param {Boolean} args.fastify
27
+ * @param {import('../../../../').Config['database']} args.db
10
28
  */
11
- const mongoF = async ({ projectName, fastify }) => {
12
- const createFoldersCommand = `mkdir ${projectName}/src/database/mongo \
13
- ${projectName}/src/database/mongo/models \
14
- ${projectName}/src/database/mongo/queries`
29
+ const db = async ({ projectName, db }) => {
30
+ const isMongo = db === 'mongo'
31
+ const createFoldersCommands = `mkdir ${projectName}/prisma \
32
+ ${projectName}/src/database/${db} \
33
+ ${projectName}/src/database/${db}/queries`
15
34
 
16
35
  if (platform() === 'win32')
17
- await exec(createFoldersCommand.replaceAll('/', '\\'))
18
- else await exec(createFoldersCommand)
36
+ await exec(createFoldersCommands.replaceAll('/', '\\'))
37
+ else await exec(createFoldersCommands)
19
38
 
20
39
  const database = {
21
- index: {
22
- content: "export * from './mongo'\n",
23
- file: `${projectName}/src/database/index.ts`
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.DB_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
- })
40
+ schema: {
41
+ content: `generator client {
42
+ provider = "prisma-client-js"
43
+ }
75
44
 
76
- return {
77
- connect: () => connect(process.env.DB_URI as string, connectionConfig),
78
- disconnect: () => connection.close()
79
- }
45
+ datasource db {
46
+ provider = "${dbPrismaName[db]}"
47
+ url = ${db !== 'sqlite' ? 'env("DATABASE_URL")' : '"file:./dev.db"'}
80
48
  }
81
49
 
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
50
+ model User {
51
+ ${
52
+ isMongo
53
+ ? `id String @id @default(auto()) @map("_id") @db.ObjectId
54
+ lastName String
55
+ name String`
56
+ : `id Int @id @default(autoincrement())
57
+ lastName String
58
+ name String`
98
59
  }
99
60
 
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.DB_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
- })
61
+ createdAt DateTime @default(now())
62
+ updatedAt DateTime @updatedAt
131
63
 
132
- return {
133
- connect: () => connect(process.env.DB_URI as string, connectionConfig),
134
- disconnect: () => connection.close()
135
- }
64
+ @@map("users")
136
65
  }
137
-
138
- export { dbConnection }
139
66
  `,
140
- file: `${projectName}/src/database/mongo/connection.ts`
141
- },
67
+ file: `${projectName}/prisma/schema.prisma`
68
+ },
69
+ index: {
70
+ content: `export * from './${db}'\n`,
71
+ file: `${projectName}/src/database/index.ts`
72
+ },
73
+ [db]: {
142
74
  index: {
143
- content: `export * from './models'
144
- export * from './queries'
145
- export * from './connection'
146
- `,
147
- file: `${projectName}/src/database/mongo/index.ts`
75
+ content: `export * from './connection'
76
+ export * from './queries'\n`,
77
+ file: `${projectName}/src/database/${db}/index.ts`
148
78
  },
149
- models: {
150
- index: {
151
- content: "export * from './user'\n",
152
- file: `${projectName}/src/database/mongo/models/index.ts`
153
- },
154
- user: {
155
- content: `import { model, Schema } from 'mongoose'
79
+ connection: {
80
+ content: `import { PrismaClient } from '@prisma/client'
81
+ import { Debugger } from 'debug'
82
+
83
+ let dbConnected = false
84
+
85
+ declare global {
86
+ // eslint-disable-next-line no-var
87
+ var __client__: PrismaClient
88
+ }
156
89
 
157
- const UserSchema = new Schema<UserDBO>(
158
- {
159
- lastName: {
160
- required: true,
161
- type: String
90
+ const dbConnection = (
91
+ d?: Debugger
92
+ ): {
93
+ connect: () => Promise<PrismaClient>
94
+ disconnect: () => Promise<boolean>
95
+ } => {
96
+ return {
97
+ connect: async () => {
98
+ if (!global.__client__) {
99
+ global.__client__ = new PrismaClient()
100
+ await global.__client__.$connect()
101
+ dbConnected = true
102
+ d?.('${dbPrettyName[db]} connection established.')
103
+ }
104
+
105
+ return global.__client__
162
106
  },
163
- name: {
164
- required: true,
165
- type: String
166
- }
167
- },
168
- {
169
- timestamps: true,
170
- versionKey: false,
171
- toObject: {
172
- transform: (_, ret) => {
173
- ret.id = ret._id.toString()
174
- delete ret._id
107
+ disconnect: async () => {
108
+ if (global.__client__) {
109
+ dbConnected = false
110
+ await global.__client__.$disconnect()
111
+ d?.('${dbPrettyName[db]} connection closed.')
175
112
  }
113
+
114
+ return dbConnected
176
115
  }
177
116
  }
178
- )
179
-
180
- const UserModel = model<UserDBO>('users', UserSchema)
117
+ }
181
118
 
182
- export { UserModel }
183
- `,
184
- file: `${projectName}/src/database/mongo/models/user.ts`
185
- }
119
+ export { dbConnection }\n`,
120
+ file: `${projectName}/src/database/${db}/connection.ts`
186
121
  },
187
122
  queries: {
188
123
  index: {
189
124
  content: "export * from './user'\n",
190
- file: `${projectName}/src/database/mongo/queries/index.ts`
125
+ file: `${projectName}/src/database/${db}/queries/index.ts`
191
126
  },
192
127
  user: {
193
- content: `import { Document, MergeType, Types } from 'mongoose'
194
-
195
- import { UserModel } from '..'
196
- import { User, UserDTO, UserWithId } from 'schemas'
197
-
198
- const userDBOtoDTO = (
199
- userDBO: Document<unknown, unknown, MergeType<UserDBO, UserDBO>> &
200
- Omit<UserDBO, keyof UserDBO> &
201
- UserDBO & {
202
- _id: Types.ObjectId
203
- }
204
- ): UserDTO => ({
205
- ...userDBO.toObject(),
206
- createdAt: userDBO.createdAt.toISOString(),
207
- updatedAt: userDBO.updatedAt.toISOString()
208
- })
209
-
210
- const store = async (userData: User): Promise<UserDTO> => {
211
- const user = new UserModel(userData)
212
-
213
- await user.save()
214
-
215
- return userDBOtoDTO(user)
128
+ content: `import { User } from '@prisma/client'
129
+ import debug from 'debug'
130
+
131
+ import { dbConnection } from '../connection'
132
+ import { Id, User as UserSchema, UserDTO } from 'schemas'
133
+ import { Logger } from 'utils'
134
+
135
+ const LOGGER = new Logger(debug('App:Database:Queries:User'))
136
+
137
+ const userDBOtoDTO = (userDBO: User): UserDTO =>
138
+ ({
139
+ ...userDBO,
140
+ createdAt: userDBO.createdAt.toISOString(),
141
+ updatedAt: userDBO.updatedAt.toISOString()
142
+ }) as UserDTO
143
+
144
+ const store = async (userData: UserSchema) => {
145
+ try {
146
+ const client = await dbConnection().connect()
147
+ const user = await client.user.create({
148
+ data: userData
149
+ })
150
+
151
+ return userDBOtoDTO(user)
152
+ } catch (error) {
153
+ LOGGER.log({
154
+ origin: 'queries/user.ts',
155
+ method: store.name,
156
+ value: 'error',
157
+ content: error
158
+ })
159
+
160
+ return null
161
+ }
216
162
  }
217
163
 
218
- const remove = async (
219
- id: string | null = null
220
- ): Promise<UserDTO | number | null> => {
221
- if (id) {
222
- const removedUser = await UserModel.findByIdAndRemove(id)
223
-
224
- if (!removedUser) return null
225
-
226
- return userDBOtoDTO(removedUser)
164
+ const removeById = async (id: Id) => {
165
+ try {
166
+ const client = await dbConnection().connect()
167
+ await client.user.delete({
168
+ where: { id }
169
+ })
170
+
171
+ return true
172
+ } catch (error) {
173
+ LOGGER.log({
174
+ origin: 'queries/user.ts',
175
+ method: removeById.name,
176
+ value: 'error',
177
+ content: error
178
+ })
179
+
180
+ return false
227
181
  }
228
-
229
- return (await UserModel.deleteMany({})).deletedCount
230
182
  }
231
183
 
232
- const get = async (
233
- id: string | null = null
234
- ): Promise<UserDTO[] | UserDTO | null> => {
235
- if (id) {
236
- const user = await UserModel.findById(id)
237
-
238
- return user ? userDBOtoDTO(user) : null
184
+ const getById = async (id: Id) => {
185
+ try {
186
+ const client = await dbConnection().connect()
187
+ const user = await client.user.findUnique({
188
+ where: { id }
189
+ })
190
+
191
+ if (!user) return null
192
+
193
+ return userDBOtoDTO(user)
194
+ } catch (error) {
195
+ LOGGER.log({
196
+ origin: 'queries/user.ts',
197
+ method: getById.name,
198
+ value: 'error',
199
+ content: error
200
+ })
201
+
202
+ return null
239
203
  }
240
-
241
- const users = await UserModel.find({})
242
-
243
- return users.map(u => userDBOtoDTO(u))
244
204
  }
245
205
 
246
- const update = async (userData: UserWithId): Promise<UserDTO | null> => {
247
- const { id, ...rest } = userData
248
- const user = await UserModel.findByIdAndUpdate(id, rest, { new: true })
249
-
250
- return user ? userDBOtoDTO(user) : null
206
+ const update = async (id: Id, user: UserSchema) => {
207
+ try {
208
+ const client = await dbConnection().connect()
209
+ const userUpdated = await client.user.update({
210
+ where: { id },
211
+ data: user
212
+ })
213
+
214
+ if (!userUpdated) return null
215
+
216
+ return userDBOtoDTO(userUpdated)
217
+ } catch (error) {
218
+ LOGGER.log({
219
+ origin: 'queries/user.ts',
220
+ method: update.name,
221
+ value: 'error',
222
+ content: error
223
+ })
224
+
225
+ return null
226
+ }
251
227
  }
252
228
 
253
- export { store, remove, get, update }
254
- `,
255
- file: `${projectName}/src/database/mongo/queries/user.ts`
229
+ export { store, removeById, getById, update }\n`,
230
+ file: `${projectName}/src/database/${db}/queries/user.ts`
256
231
  }
257
232
  }
258
233
  }
259
234
  }
260
235
 
261
236
  await Promise.all([
237
+ writeFile(database.schema.file, database.schema.content),
262
238
  writeFile(database.index.file, database.index.content),
239
+ writeFile(database[db].connection.file, database[db].connection.content),
240
+ writeFile(database[db].index.file, database[db].index.content),
263
241
  writeFile(
264
- database.mongo.connection.file,
265
- database.mongo.connection.content
266
- ),
267
- writeFile(database.mongo.index.file, database.mongo.index.content),
268
- writeFile(
269
- database.mongo.models.index.file,
270
- database.mongo.models.index.content
271
- ),
272
- writeFile(
273
- database.mongo.models.user.file,
274
- database.mongo.models.user.content
275
- ),
276
- writeFile(
277
- database.mongo.queries.index.file,
278
- database.mongo.queries.index.content
242
+ database[db].queries.index.file,
243
+ database[db].queries.index.content
279
244
  ),
280
- writeFile(
281
- database.mongo.queries.user.file,
282
- database.mongo.queries.user.content
283
- )
245
+ writeFile(database[db].queries.user.file, database[db].queries.user.content)
284
246
  ])
285
247
  }
286
248
 
287
249
  /**
288
250
  * @param {Object} args
289
- * @param {Boolean|undefined} args.mongo
251
+ * @param {import('../../../../').Config['database']} args.database
290
252
  * @param {String} args.projectName
291
- * @param {Boolean} args.fastify
292
253
  */
293
- module.exports = async ({ mongo = true, projectName, fastify }) => {
254
+ module.exports = async ({ database, projectName }) => {
294
255
  const createFoldersCommand = `mkdir ${projectName}/src/database`
295
256
 
296
257
  if (platform() === 'win32')
297
258
  await exec(createFoldersCommand.replaceAll('/', '\\'))
298
259
  else await exec(createFoldersCommand)
299
260
 
300
- if (mongo) await mongoF({ projectName, fastify })
261
+ await db({ db: database, projectName })
301
262
  }