@anthonylzq/simba.js 4.2.0 → 4.4.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/lib/src/functions/api/database.js +175 -0
- package/lib/src/functions/api/index.js +220 -0
- package/lib/src/functions/api/network.js +906 -0
- package/lib/src/functions/api/schemas.js +72 -0
- package/lib/src/functions/api/services.js +218 -0
- package/lib/src/functions/api/types.js +80 -0
- package/lib/src/functions/api/utils.js +453 -0
- package/lib/src/index.js +1 -1
- package/lib/src/utils/titleCase.js +1 -1
- package/lib/src/utils/writeFile.js +2 -2
- package/package.json +16 -6
- package/lib/src/functions/api.js +0 -1982
|
@@ -0,0 +1,72 @@
|
|
|
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/schemas`
|
|
12
|
+
|
|
13
|
+
if (platform() === 'win32')
|
|
14
|
+
await exec(createFoldersCommand.replaceAll('/', '\\'))
|
|
15
|
+
else await exec(createFoldersCommand)
|
|
16
|
+
|
|
17
|
+
const schemas = {
|
|
18
|
+
index: {
|
|
19
|
+
content: `import { Static, Type } from '@sinclair/typebox'
|
|
20
|
+
|
|
21
|
+
const id = Type.String({
|
|
22
|
+
pattern: '^[a-zA-Z0-9]{24,}$'
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
type Id = Static<typeof id>
|
|
26
|
+
|
|
27
|
+
const idSchema = Type.Object({ id })
|
|
28
|
+
|
|
29
|
+
type IdSchema = Static<typeof idSchema>
|
|
30
|
+
|
|
31
|
+
export { id, Id, idSchema, IdSchema }
|
|
32
|
+
export * from './user'
|
|
33
|
+
`,
|
|
34
|
+
file: `${projectName}/src/schemas/index.ts`
|
|
35
|
+
},
|
|
36
|
+
user: {
|
|
37
|
+
content: `import { Static, Type } from '@sinclair/typebox'
|
|
38
|
+
|
|
39
|
+
import { id } from '.'
|
|
40
|
+
|
|
41
|
+
const user = Type.Object({
|
|
42
|
+
lastName: Type.String(),
|
|
43
|
+
name: Type.String()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
type User = Static<typeof user>
|
|
47
|
+
|
|
48
|
+
const userDto = Type.Object({
|
|
49
|
+
id: Type.Optional(id),
|
|
50
|
+
lastName: Type.String(),
|
|
51
|
+
name: Type.String(),
|
|
52
|
+
createdAt: Type.Optional(Type.String()),
|
|
53
|
+
updatedAt: Type.Optional(Type.String())
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
type UserDTO = Static<typeof userDto>
|
|
57
|
+
|
|
58
|
+
const storeUserSchema = Type.Object({
|
|
59
|
+
args: user
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
type StoreUser = Static<typeof storeUserSchema>
|
|
63
|
+
|
|
64
|
+
export { userDto, UserDTO, user, User, storeUserSchema, StoreUser }
|
|
65
|
+
`,
|
|
66
|
+
file: `${projectName}/src/schemas/user.ts`
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await writeFile(schemas.index.file, schemas.index.content)
|
|
71
|
+
await writeFile(schemas.user.file, schemas.user.content)
|
|
72
|
+
}
|
|
@@ -0,0 +1,218 @@
|
|
|
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 writeFile(services.index.file, services.index.content)
|
|
208
|
+
await writeFile(services.user.file, services.user.content)
|
|
209
|
+
await writeFile(services.utils.index.file, services.utils.index.content)
|
|
210
|
+
await writeFile(
|
|
211
|
+
services['utils/messages'].index.file,
|
|
212
|
+
services['utils/messages'].index.content
|
|
213
|
+
)
|
|
214
|
+
await writeFile(
|
|
215
|
+
services['utils/messages'].user.file,
|
|
216
|
+
services['utils/messages'].user.content
|
|
217
|
+
)
|
|
218
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
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
|
+
*/
|
|
11
|
+
module.exports = async ({ express, projectName }) => {
|
|
12
|
+
const createFoldersCommand = `mkdir ${projectName}/src/@types \
|
|
13
|
+
${projectName}/src/@types/models \
|
|
14
|
+
${express ? `${projectName}/src/@types/custom` : ''}`
|
|
15
|
+
|
|
16
|
+
if (platform() === 'win32')
|
|
17
|
+
await exec(createFoldersCommand.replaceAll('/', '\\'))
|
|
18
|
+
else await exec(createFoldersCommand)
|
|
19
|
+
|
|
20
|
+
const types = {
|
|
21
|
+
index: {
|
|
22
|
+
content: `/* eslint-disable no-var */
|
|
23
|
+
declare global {}
|
|
24
|
+
|
|
25
|
+
export {}
|
|
26
|
+
`,
|
|
27
|
+
file: `${projectName}/src/@types/index.d.ts`
|
|
28
|
+
},
|
|
29
|
+
models: {
|
|
30
|
+
user: {
|
|
31
|
+
content: `interface UserDBO {
|
|
32
|
+
id: string
|
|
33
|
+
name: string
|
|
34
|
+
lastName: string
|
|
35
|
+
createdAt: Date
|
|
36
|
+
updatedAt: Date
|
|
37
|
+
}
|
|
38
|
+
`,
|
|
39
|
+
file: `${projectName}/src/@types/models/user.d.ts`
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
...(express && {
|
|
43
|
+
custom: {
|
|
44
|
+
request: {
|
|
45
|
+
content: `type ExpressRequest = import('express').Request
|
|
46
|
+
|
|
47
|
+
interface CustomRequest extends ExpressRequest {
|
|
48
|
+
body: {
|
|
49
|
+
args?: import('schemas').UserDTO
|
|
50
|
+
}
|
|
51
|
+
// We can add custom headers via intersection, remember that for some reason
|
|
52
|
+
// headers must be in Snake-Pascal-Case
|
|
53
|
+
headers: import('http').IncomingHttpHeaders & {
|
|
54
|
+
'Custom-Header'?: string
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
`,
|
|
58
|
+
file: `${projectName}/src/@types/custom/request.d.ts`
|
|
59
|
+
},
|
|
60
|
+
response: {
|
|
61
|
+
content: `type ExpressResponse = import('express').Response
|
|
62
|
+
|
|
63
|
+
interface CustomResponse extends ExpressResponse {
|
|
64
|
+
newValue?: string
|
|
65
|
+
}
|
|
66
|
+
`,
|
|
67
|
+
file: `${projectName}/src/@types/custom/response.d.ts`
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await writeFile(types.index.file, types.index.content)
|
|
74
|
+
await writeFile(types.models.user.file, types.models.user.content)
|
|
75
|
+
|
|
76
|
+
if (express) {
|
|
77
|
+
await writeFile(types.custom.request.file, types.custom.request.content)
|
|
78
|
+
await writeFile(types.custom.response.file, types.custom.response.content)
|
|
79
|
+
}
|
|
80
|
+
}
|