@anthonylzq/simba.js 4.3.0 → 5.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.
@@ -0,0 +1,122 @@
1
+ const { platform } = require('os')
2
+ const { promisify } = require('util')
3
+ const exec = promisify(require('child_process').exec)
4
+ const writeFile = require('../../utils/writeFile')
5
+
6
+ /**
7
+ * @param {Object} args
8
+ * @param {String} args.projectName
9
+ * @param {Boolean} args.graphql
10
+ */
11
+ module.exports = async ({ projectName, graphql }) => {
12
+ const createFoldersCommand = `mkdir ${projectName}/src/schemas`
13
+
14
+ if (platform() === 'win32')
15
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
16
+ else await exec(createFoldersCommand)
17
+
18
+ const schemas = {
19
+ index: {
20
+ content: `import { Static, Type } from '@sinclair/typebox'
21
+
22
+ const id = Type.String({
23
+ pattern: '^[a-zA-Z0-9]{24,}$'
24
+ })
25
+
26
+ type Id = Static<typeof id>
27
+
28
+ const idSchema = Type.Object({ id })
29
+
30
+ type IdSchema = Static<typeof idSchema>
31
+
32
+ export { id, Id, idSchema, IdSchema }
33
+ export * from './user'
34
+ `,
35
+ file: `${projectName}/src/schemas/index.ts`
36
+ },
37
+ user: {
38
+ content: `import { Static, Type } from '@sinclair/typebox'
39
+
40
+ import { id } from '.'
41
+
42
+ const user = Type.Object({
43
+ lastName: Type.String(),
44
+ name: Type.String()
45
+ })
46
+
47
+ type User = Static<typeof user>
48
+
49
+ const userDto = Type.Object({
50
+ id: Type.Optional(id),
51
+ lastName: Type.String(),
52
+ name: Type.String(),
53
+ createdAt: Type.Optional(Type.String()),
54
+ updatedAt: Type.Optional(Type.String())
55
+ })
56
+
57
+ type UserDTO = Static<typeof userDto>
58
+
59
+ const storeUserSchema = Type.Object({
60
+ args: user
61
+ })
62
+
63
+ type StoreUser = Static<typeof storeUserSchema>
64
+
65
+ export { userDto, UserDTO, user, User, storeUserSchema, StoreUser }
66
+ `,
67
+ file: `${projectName}/src/schemas/user.ts`
68
+ }
69
+ }
70
+
71
+ if (graphql) {
72
+ schemas.index.content = `import { Static, Type } from '@sinclair/typebox'
73
+ import Ajv from 'ajv/dist/2019.js'
74
+ import addFormats from 'ajv-formats'
75
+
76
+ const id = Type.String({
77
+ pattern: '^[a-zA-Z0-9]{24,}$'
78
+ })
79
+
80
+ type ID = Static<typeof id>
81
+
82
+ const idSchema = Type.Object({ id })
83
+
84
+ type IDSchema = Static<typeof idSchema>
85
+
86
+ const ajv = addFormats(new Ajv(), ['email'])
87
+ .addKeyword('kind')
88
+ .addKeyword('modifier')
89
+
90
+ export { id, ID, idSchema, IDSchema, ajv }
91
+ export * from './user'
92
+ `
93
+ schemas.user.content = `import { Static, Type } from '@sinclair/typebox'
94
+
95
+ import { id } from '.'
96
+
97
+ const user = Type.Object({
98
+ lastName: Type.String(),
99
+ name: Type.String()
100
+ })
101
+
102
+ type User = Static<typeof user>
103
+
104
+ const userDto = Type.Object({
105
+ id: Type.Optional(id),
106
+ lastName: Type.String(),
107
+ name: Type.String(),
108
+ createdAt: Type.Optional(Type.String()),
109
+ updatedAt: Type.Optional(Type.String())
110
+ })
111
+
112
+ type UserDTO = Static<typeof userDto>
113
+
114
+ export { userDto, UserDTO, user, User }
115
+ `
116
+ }
117
+
118
+ await Promise.all([
119
+ writeFile(schemas.index.file, schemas.index.content),
120
+ writeFile(schemas.user.file, schemas.user.content)
121
+ ])
122
+ }
@@ -0,0 +1,220 @@
1
+ const { platform } = require('os')
2
+ const { promisify } = require('util')
3
+ const exec = promisify(require('child_process').exec)
4
+ const writeFile = require('../../utils/writeFile')
5
+
6
+ /**
7
+ * @param {Object} args
8
+ * @param {String} args.projectName
9
+ */
10
+ module.exports = async ({ projectName }) => {
11
+ const createFoldersCommand = `mkdir ${projectName}/src/services \
12
+ ${projectName}/src/services/utils \
13
+ ${projectName}/src/services/utils/messages`
14
+
15
+ if (platform() === 'win32')
16
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
17
+ else await exec(createFoldersCommand)
18
+
19
+ const services = {
20
+ index: {
21
+ content: "export * from './user'\n",
22
+ file: `${projectName}/src/services/index.ts`
23
+ },
24
+ user: {
25
+ content: `import httpErrors from 'http-errors'
26
+
27
+ import { store, remove, get, update } from 'database'
28
+ import { UserDTO } from 'schemas'
29
+ import { EFU, MFU, GE, errorHandling } from './utils'
30
+
31
+ type Process = {
32
+ type: 'store' | 'getAll' | 'deleteAll' | 'getOne' | 'update' | 'delete'
33
+ }
34
+
35
+ type Arguments = {
36
+ id?: string
37
+ userDto?: UserDTO
38
+ userDtoWithoutId?: Omit<UserDTO, 'id'>
39
+ }
40
+
41
+ class UserService {
42
+ #args: Arguments
43
+
44
+ constructor(args: Arguments = {}) {
45
+ this.#args = args
46
+ }
47
+
48
+ public process({ type }: Process): Promise<string | UserDTO | UserDTO[]> {
49
+ switch (type) {
50
+ case 'store':
51
+ return this.#store()
52
+ case 'getAll':
53
+ return this.#getAll()
54
+ case 'deleteAll':
55
+ return this.#deleteAll()
56
+ case 'getOne':
57
+ return this.#getOne()
58
+ case 'update':
59
+ return this.#update()
60
+ case 'delete':
61
+ return this.#delete()
62
+ default:
63
+ throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
64
+ }
65
+ }
66
+
67
+ async #store(): Promise<UserDTO> {
68
+ try {
69
+ if (!this.#args.userDtoWithoutId)
70
+ throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
71
+
72
+ const result = await store({
73
+ ...this.#args.userDtoWithoutId
74
+ })
75
+
76
+ return result
77
+ } catch (e) {
78
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
79
+ }
80
+ }
81
+
82
+ async #getAll(): Promise<UserDTO[]> {
83
+ try {
84
+ const users = (await get()) as UserDTO[]
85
+
86
+ return users
87
+ } catch (e) {
88
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
89
+ }
90
+ }
91
+
92
+ async #deleteAll(): Promise<string> {
93
+ try {
94
+ const usersDeleted = (await remove()) as number
95
+
96
+ if (usersDeleted >= 1) return MFU.ALL_USERS_DELETED
97
+
98
+ if (usersDeleted === 0)
99
+ throw new httpErrors.Conflict(EFU.NOTHING_TO_DELETE)
100
+
101
+ throw new httpErrors.InternalServerError(GE.INTERNAL_SERVER_ERROR)
102
+ } catch (e) {
103
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
104
+ }
105
+ }
106
+
107
+ async #getOne(): Promise<UserDTO> {
108
+ try {
109
+ if (!this.#args.id)
110
+ throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
111
+
112
+ const { id } = this.#args
113
+ const user = (await get(id)) as UserDTO | null
114
+
115
+ if (!user) throw new httpErrors.NotFound(EFU.NOT_FOUND)
116
+
117
+ return user
118
+ } catch (e) {
119
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
120
+ }
121
+ }
122
+
123
+ async #update(): Promise<UserDTO> {
124
+ try {
125
+ if (!this.#args.userDto || !this.#args.userDto.id)
126
+ throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
127
+
128
+ const updatedUser = await update(this.#args.userDto)
129
+
130
+ if (!updatedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
131
+
132
+ return updatedUser
133
+ } catch (e) {
134
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
135
+ }
136
+ }
137
+
138
+ async #delete(): Promise<string> {
139
+ try {
140
+ if (!this.#args.id)
141
+ throw new httpErrors.UnprocessableEntity(GE.INTERNAL_SERVER_ERROR)
142
+
143
+ const { id } = this.#args
144
+ const deletedUser = await remove(id)
145
+
146
+ if (!deletedUser) throw new httpErrors.NotFound(EFU.NOT_FOUND)
147
+
148
+ return MFU.USER_DELETED
149
+ } catch (e) {
150
+ return errorHandling(e, GE.INTERNAL_SERVER_ERROR)
151
+ }
152
+ }
153
+ }
154
+
155
+ export { UserService }
156
+ `,
157
+ file: `${projectName}/src/services/user.ts`
158
+ },
159
+ utils: {
160
+ index: {
161
+ content: `import httpErrors from 'http-errors'
162
+
163
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
164
+ const errorHandling = (e: any, message?: string): never => {
165
+ console.error(e)
166
+
167
+ if (e instanceof httpErrors.HttpError) throw e
168
+
169
+ throw new httpErrors.InternalServerError(message ?? e.message)
170
+ }
171
+
172
+ export { errorHandling }
173
+ export * from './messages'
174
+ `,
175
+ file: `${projectName}/src/services/utils/index.ts`
176
+ }
177
+ },
178
+ 'utils/messages': {
179
+ index: {
180
+ content: `enum GenericErrors {
181
+ INTERNAL_SERVER_ERROR = 'Something went wrong'
182
+ }
183
+
184
+ export { GenericErrors as GE }
185
+ export * from './user'
186
+ `,
187
+ file: `${projectName}/src/services/utils/messages/index.ts`
188
+ },
189
+ user: {
190
+ content: `enum ErrorForUser {
191
+ NOT_FOUND = 'The requested user does not exists',
192
+ NOTHING_TO_DELETE = 'There is no user to be deleted'
193
+ }
194
+
195
+ enum MessageForUser {
196
+ ALL_USERS_DELETED = 'All the users were deleted successfully',
197
+ USER_DELETED = 'The requested user was successfully deleted'
198
+ }
199
+
200
+ export { ErrorForUser as EFU, MessageForUser as MFU }
201
+ `,
202
+ file: `${projectName}/src/services/utils/messages/user.ts`
203
+ }
204
+ }
205
+ }
206
+
207
+ await Promise.all([
208
+ await writeFile(services.index.file, services.index.content),
209
+ await writeFile(services.user.file, services.user.content),
210
+ await writeFile(services.utils.index.file, services.utils.index.content),
211
+ await writeFile(
212
+ services['utils/messages'].index.file,
213
+ services['utils/messages'].index.content
214
+ ),
215
+ await writeFile(
216
+ services['utils/messages'].user.file,
217
+ services['utils/messages'].user.content
218
+ )
219
+ ])
220
+ }
@@ -0,0 +1,110 @@
1
+ const { platform } = require('os')
2
+ const { promisify } = require('util')
3
+ const exec = promisify(require('child_process').exec)
4
+ const writeFile = require('../../utils/writeFile')
5
+
6
+ /**
7
+ * @param {Object} args
8
+ * @param {Boolean} args.express
9
+ * @param {String} args.projectName
10
+ * @param {Boolean} args.graphql
11
+ */
12
+ module.exports = async ({ express, projectName, graphql }) => {
13
+ const createFoldersCommand = `mkdir ${projectName}/src/@types \
14
+ ${projectName}/src/@types/models \
15
+ ${express ? `${projectName}/src/@types/custom` : ''} ${
16
+ graphql ? `${projectName}/src/@types/graphQL` : ''
17
+ }`
18
+
19
+ if (platform() === 'win32')
20
+ await exec(createFoldersCommand.replaceAll('/', '\\'))
21
+ else await exec(createFoldersCommand)
22
+
23
+ const types = {
24
+ index: {
25
+ content: `/* eslint-disable no-var */
26
+ declare global {}
27
+
28
+ export {}
29
+ `,
30
+ file: `${projectName}/src/@types/index.d.ts`
31
+ },
32
+ models: {
33
+ user: {
34
+ content: `interface UserDBO {
35
+ id: string
36
+ name: string
37
+ lastName: string
38
+ createdAt: Date
39
+ updatedAt: Date
40
+ }
41
+ `,
42
+ file: `${projectName}/src/@types/models/user.d.ts`
43
+ }
44
+ },
45
+ ...(express && {
46
+ custom: {
47
+ request: {
48
+ content: `type ExpressRequest = import('express').Request
49
+
50
+ interface CustomRequest extends ExpressRequest {
51
+ log: import('express-pino-logger').HttpLogger['logger']
52
+ body: {
53
+ args?: import('schemas').UserDTO
54
+ }
55
+ // We can add custom headers via intersection, remember that for some reason
56
+ // headers must be in Snake-Pascal-Case
57
+ headers: import('http').IncomingHttpHeaders & {
58
+ 'Custom-Header'?: string
59
+ }
60
+ }
61
+ `,
62
+ file: `${projectName}/src/@types/custom/request.d.ts`
63
+ },
64
+ response: {
65
+ content: `type ExpressResponse = import('express').Response
66
+
67
+ interface CustomResponse extends ExpressResponse {
68
+ newValue?: string
69
+ }
70
+ `,
71
+ file: `${projectName}/src/@types/custom/response.d.ts`
72
+ }
73
+ }
74
+ }),
75
+ ...(graphql && {
76
+ graphQL: {
77
+ context: {
78
+ content: express
79
+ ? `type Context = {
80
+ log: import('express-pino-logger').HttpLogger['logger']
81
+ }
82
+ `
83
+ : `type Context = {
84
+ log: import('fastify').FastifyInstance['log']
85
+ }
86
+ `,
87
+ file: `${projectName}/src/@types/graphQL/context.d.ts`
88
+ }
89
+ }
90
+ })
91
+ }
92
+ const processes = [
93
+ writeFile(types.index.file, types.index.content),
94
+ writeFile(types.models.user.file, types.models.user.content)
95
+ ]
96
+
97
+ if (express) {
98
+ processes.concat([
99
+ writeFile(types.custom.request.file, types.custom.request.content),
100
+ writeFile(types.custom.response.file, types.custom.response.content)
101
+ ])
102
+ }
103
+
104
+ if (graphql)
105
+ processes.push(
106
+ writeFile(types.graphQL.context.file, types.graphQL.context.content)
107
+ )
108
+
109
+ await Promise.all(processes)
110
+ }