@skalfa/skalfa-api-core 1.0.2 → 1.0.7

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.
Files changed (272) hide show
  1. package/CONTRIBUTING.md +45 -0
  2. package/LICENSE +21 -0
  3. package/README.md +60 -0
  4. package/dist/auth/auth.d.ts +18 -15
  5. package/dist/auth/auth.js +20 -203
  6. package/dist/auth/auth.js.map +1 -1
  7. package/dist/auth/create-access-token.d.ts +4 -0
  8. package/dist/auth/create-access-token.js +26 -0
  9. package/dist/auth/create-access-token.js.map +1 -0
  10. package/dist/auth/create-user-mail-token.d.ts +4 -0
  11. package/dist/auth/create-user-mail-token.js +19 -0
  12. package/dist/auth/create-user-mail-token.js.map +1 -0
  13. package/dist/auth/helpers/generate-agent-id.d.ts +1 -0
  14. package/dist/auth/helpers/generate-agent-id.js +7 -0
  15. package/dist/auth/helpers/generate-agent-id.js.map +1 -0
  16. package/dist/auth/helpers/get-request-ip.d.ts +1 -0
  17. package/dist/auth/helpers/get-request-ip.js +4 -0
  18. package/dist/auth/helpers/get-request-ip.js.map +1 -0
  19. package/dist/auth/helpers/get-user-permissions.d.ts +1 -0
  20. package/dist/auth/helpers/get-user-permissions.js +9 -0
  21. package/dist/auth/helpers/get-user-permissions.js.map +1 -0
  22. package/dist/auth/helpers/index.d.ts +3 -0
  23. package/dist/auth/helpers/index.js +4 -0
  24. package/dist/auth/helpers/index.js.map +1 -0
  25. package/dist/auth/list-user-sessions.d.ts +1 -0
  26. package/dist/auth/list-user-sessions.js +10 -0
  27. package/dist/auth/list-user-sessions.js.map +1 -0
  28. package/dist/auth/revalidate-user-permissions-by-role.d.ts +1 -0
  29. package/dist/auth/revalidate-user-permissions-by-role.js +12 -0
  30. package/dist/auth/revalidate-user-permissions-by-role.js.map +1 -0
  31. package/dist/auth/revalidate-user-permissions.d.ts +1 -0
  32. package/dist/auth/revalidate-user-permissions.js +21 -0
  33. package/dist/auth/revalidate-user-permissions.js.map +1 -0
  34. package/dist/auth/revoke-access-token.d.ts +1 -0
  35. package/dist/auth/revoke-access-token.js +5 -0
  36. package/dist/auth/revoke-access-token.js.map +1 -0
  37. package/dist/auth/verify-access-token.d.ts +1 -0
  38. package/dist/auth/verify-access-token.js +47 -0
  39. package/dist/auth/verify-access-token.js.map +1 -0
  40. package/dist/auth/verify-user-mail-token.d.ts +1 -0
  41. package/dist/auth/verify-user-mail-token.js +21 -0
  42. package/dist/auth/verify-user-mail-token.js.map +1 -0
  43. package/dist/commands/cli.js +5 -3
  44. package/dist/commands/cli.js.map +1 -1
  45. package/dist/commands/make/basic-controller.js +1 -1
  46. package/dist/commands/make/basic-controller.js.map +1 -1
  47. package/dist/commands/make/basic-migration.d.ts +1 -1
  48. package/dist/commands/make/basic-migration.js +2 -2
  49. package/dist/commands/make/basic-migration.js.map +1 -1
  50. package/dist/commands/make/basic-model.js +1 -1
  51. package/dist/commands/make/basic-model.js.map +1 -1
  52. package/dist/commands/make/basic-seeder.js +1 -1
  53. package/dist/commands/make/basic-seeder.js.map +1 -1
  54. package/dist/commands/make/blueprint.js +1 -1
  55. package/dist/commands/make/blueprint.js.map +1 -1
  56. package/dist/commands/make/da-migration.js +3 -3
  57. package/dist/commands/make/da-migration.js.map +1 -1
  58. package/dist/commands/make/mail.js +2 -2
  59. package/dist/commands/make/mail.js.map +1 -1
  60. package/dist/commands/make/notification.js +1 -1
  61. package/dist/commands/make/notification.js.map +1 -1
  62. package/dist/commands/make/queue.js +1 -1
  63. package/dist/commands/make/queue.js.map +1 -1
  64. package/dist/commands/make/resource.d.ts +2 -0
  65. package/dist/commands/make/resource.js +19 -0
  66. package/dist/commands/make/resource.js.map +1 -0
  67. package/dist/commands/make/{light-controller.js → skalfa-controller.js} +3 -3
  68. package/dist/commands/make/skalfa-controller.js.map +1 -0
  69. package/dist/commands/make/{light-model.js → skalfa-model.js} +4 -4
  70. package/dist/commands/make/skalfa-model.js.map +1 -0
  71. package/dist/commands/runner/barrels.js.map +1 -1
  72. package/dist/commands/runner/blueprint/controller-generation.js.map +1 -1
  73. package/dist/commands/runner/blueprint/documentation-generation.js.map +1 -1
  74. package/dist/commands/runner/blueprint/migration-generation.js +1 -1
  75. package/dist/commands/runner/blueprint/migration-generation.js.map +1 -1
  76. package/dist/commands/runner/blueprint/model-generation.js.map +1 -1
  77. package/dist/commands/runner/blueprint/runner.js +2 -2
  78. package/dist/commands/runner/blueprint/runner.js.map +1 -1
  79. package/dist/commands/runner/blueprint/seeder-generation.js +1 -1
  80. package/dist/commands/runner/blueprint/seeder-generation.js.map +1 -1
  81. package/dist/commands/runner/da-migration.js +1 -2
  82. package/dist/commands/runner/da-migration.js.map +1 -1
  83. package/dist/commands/runner/migration.js +1 -1
  84. package/dist/commands/runner/migration.js.map +1 -1
  85. package/dist/commands/runner/seeder.js +1 -1
  86. package/dist/commands/runner/seeder.js.map +1 -1
  87. package/dist/context/context.js +6 -0
  88. package/dist/context/context.js.map +1 -1
  89. package/dist/controller/controller.d.ts +17 -30
  90. package/dist/controller/controller.js +39 -121
  91. package/dist/controller/controller.js.map +1 -1
  92. package/dist/controller/response.d.ts +6 -0
  93. package/dist/controller/response.js +63 -0
  94. package/dist/controller/response.js.map +1 -0
  95. package/dist/controller/storage.d.ts +9 -0
  96. package/dist/controller/storage.js +56 -0
  97. package/dist/controller/storage.js.map +1 -0
  98. package/dist/conversion/conversion.d.ts +3 -0
  99. package/dist/conversion/conversion.js +28 -4
  100. package/dist/conversion/conversion.js.map +1 -1
  101. package/dist/conversion/date.d.ts +1 -0
  102. package/dist/conversion/date.js +77 -0
  103. package/dist/conversion/date.js.map +1 -0
  104. package/dist/index.d.ts +2 -0
  105. package/dist/index.js +2 -0
  106. package/dist/index.js.map +1 -1
  107. package/dist/logger/logger.js +33 -0
  108. package/dist/logger/logger.js.map +1 -1
  109. package/dist/mail/mail.js +6 -6
  110. package/dist/mail/mail.js.map +1 -1
  111. package/dist/middleware/access-log.d.ts +31 -0
  112. package/dist/middleware/access-log.js +13 -0
  113. package/dist/middleware/access-log.js.map +1 -0
  114. package/dist/middleware/auth.d.ts +37 -0
  115. package/dist/middleware/auth.js +16 -0
  116. package/dist/middleware/auth.js.map +1 -0
  117. package/dist/middleware/body-parse.d.ts +35 -0
  118. package/dist/middleware/body-parse.js +87 -0
  119. package/dist/middleware/body-parse.js.map +1 -0
  120. package/dist/middleware/context.d.ts +29 -0
  121. package/dist/middleware/context.js +8 -0
  122. package/dist/middleware/context.js.map +1 -0
  123. package/dist/middleware/cors.d.ts +31 -0
  124. package/dist/middleware/cors.js +27 -0
  125. package/dist/middleware/cors.js.map +1 -0
  126. package/dist/middleware/error-handler.d.ts +33 -0
  127. package/dist/middleware/error-handler.js +17 -0
  128. package/dist/middleware/error-handler.js.map +1 -0
  129. package/dist/middleware/middleware.d.ts +31 -10
  130. package/dist/middleware/middleware.js +41 -209
  131. package/dist/middleware/middleware.js.map +1 -1
  132. package/dist/middleware/private.d.ts +29 -0
  133. package/dist/middleware/private.js +8 -0
  134. package/dist/middleware/private.js.map +1 -0
  135. package/dist/middleware/rate-limiter.d.ts +32 -0
  136. package/dist/middleware/rate-limiter.js +30 -0
  137. package/dist/middleware/rate-limiter.js.map +1 -0
  138. package/dist/notification/index.d.ts +1 -0
  139. package/dist/notification/index.js +2 -0
  140. package/dist/notification/index.js.map +1 -0
  141. package/dist/notification/notification.d.ts +16 -0
  142. package/dist/notification/notification.js +64 -0
  143. package/dist/notification/notification.js.map +1 -0
  144. package/dist/permission/permission.js +9 -0
  145. package/dist/permission/permission.js.map +1 -1
  146. package/dist/registry/registry.d.ts +0 -6
  147. package/dist/registry/registry.js +6 -6
  148. package/dist/registry/registry.js.map +1 -1
  149. package/dist/storage/storage.d.ts +3 -3
  150. package/dist/storage/storage.js.map +1 -1
  151. package/dist/validation/validation.js +43 -51
  152. package/dist/validation/validation.js.map +1 -1
  153. package/package.json +4 -4
  154. package/src/auth/auth.ts +21 -252
  155. package/src/auth/create-access-token.ts +29 -0
  156. package/src/auth/create-user-mail-token.ts +24 -0
  157. package/src/auth/helpers/generate-agent-id.ts +8 -0
  158. package/src/auth/helpers/get-request-ip.ts +3 -0
  159. package/src/auth/helpers/get-user-permissions.ts +15 -0
  160. package/src/auth/helpers/index.ts +3 -0
  161. package/src/auth/list-user-sessions.ts +11 -0
  162. package/src/auth/revalidate-user-permissions-by-role.ts +13 -0
  163. package/src/auth/revalidate-user-permissions.ts +26 -0
  164. package/src/auth/revoke-access-token.ts +5 -0
  165. package/src/auth/verify-access-token.ts +56 -0
  166. package/src/auth/verify-user-mail-token.ts +24 -0
  167. package/src/commands/cli.ts +5 -3
  168. package/src/commands/make/basic-controller.ts +3 -1
  169. package/src/commands/make/basic-migration.ts +5 -3
  170. package/src/commands/make/basic-model.ts +3 -1
  171. package/src/commands/make/basic-seeder.ts +3 -1
  172. package/src/commands/make/blueprint.ts +3 -1
  173. package/src/commands/make/da-migration.ts +6 -5
  174. package/src/commands/make/mail.ts +4 -2
  175. package/src/commands/make/notification.ts +3 -1
  176. package/src/commands/make/queue.ts +3 -1
  177. package/src/commands/make/resource.ts +21 -0
  178. package/src/commands/make/{light-controller.ts → skalfa-controller.ts} +4 -2
  179. package/src/commands/make/{light-model.ts → skalfa-model.ts} +5 -3
  180. package/src/commands/runner/barrels.ts +4 -0
  181. package/src/commands/runner/blueprint/controller-generation.ts +2 -0
  182. package/src/commands/runner/blueprint/documentation-generation.ts +2 -0
  183. package/src/commands/runner/blueprint/migration-generation.ts +3 -1
  184. package/src/commands/runner/blueprint/model-generation.ts +2 -0
  185. package/src/commands/runner/blueprint/runner.ts +10 -2
  186. package/src/commands/runner/blueprint/seeder-generation.ts +3 -1
  187. package/src/commands/runner/da-migration.ts +3 -2
  188. package/src/commands/runner/migration.ts +1 -1
  189. package/src/commands/runner/seeder.ts +1 -1
  190. package/src/context/context.ts +23 -17
  191. package/src/controller/controller.ts +124 -239
  192. package/src/controller/response.ts +78 -0
  193. package/src/controller/storage.ts +78 -0
  194. package/src/conversion/conversion.ts +90 -64
  195. package/src/conversion/date.ts +74 -0
  196. package/src/index.ts +2 -0
  197. package/src/logger/logger.ts +217 -176
  198. package/src/mail/mail.ts +85 -85
  199. package/src/middleware/access-log.ts +15 -0
  200. package/src/middleware/auth.ts +19 -0
  201. package/src/middleware/body-parse.ts +83 -0
  202. package/src/middleware/context.ts +11 -0
  203. package/src/middleware/cors.ts +31 -0
  204. package/src/middleware/error-handler.ts +20 -0
  205. package/src/middleware/middleware.ts +91 -288
  206. package/src/middleware/private.ts +8 -0
  207. package/src/middleware/rate-limiter.ts +41 -0
  208. package/src/notification/index.ts +1 -0
  209. package/src/notification/notification.ts +86 -0
  210. package/src/permission/permission.ts +140 -136
  211. package/src/registry/registry.ts +17 -15
  212. package/src/route/route.ts +11 -11
  213. package/src/storage/storage.ts +104 -106
  214. package/src/validation/validation.ts +322 -346
  215. package/dist/auth.util.d.ts +0 -19
  216. package/dist/auth.util.js +0 -183
  217. package/dist/auth.util.js.map +0 -1
  218. package/dist/commands/make/light-controller.js.map +0 -1
  219. package/dist/commands/make/light-model.js.map +0 -1
  220. package/dist/context.util.d.ts +0 -7
  221. package/dist/context.util.js +0 -11
  222. package/dist/context.util.js.map +0 -1
  223. package/dist/controller.util.d.ts +0 -118
  224. package/dist/controller.util.js +0 -144
  225. package/dist/controller.util.js.map +0 -1
  226. package/dist/conversion.util.d.ts +0 -8
  227. package/dist/conversion.util.js +0 -52
  228. package/dist/conversion.util.js.map +0 -1
  229. package/dist/db/db.d.ts +0 -84
  230. package/dist/db/db.js +0 -177
  231. package/dist/db/db.js.map +0 -1
  232. package/dist/db/index.d.ts +0 -1
  233. package/dist/db/index.js +0 -2
  234. package/dist/db/index.js.map +0 -1
  235. package/dist/db.util.d.ts +0 -84
  236. package/dist/db.util.js +0 -177
  237. package/dist/db.util.js.map +0 -1
  238. package/dist/logger.util.d.ts +0 -30
  239. package/dist/logger.util.js +0 -126
  240. package/dist/logger.util.js.map +0 -1
  241. package/dist/mail.util.d.ts +0 -21
  242. package/dist/mail.util.js +0 -53
  243. package/dist/mail.util.js.map +0 -1
  244. package/dist/middleware.util.d.ts +0 -263
  245. package/dist/middleware.util.js +0 -233
  246. package/dist/middleware.util.js.map +0 -1
  247. package/dist/model/index.d.ts +0 -3
  248. package/dist/model/index.js +0 -4
  249. package/dist/model/index.js.map +0 -1
  250. package/dist/model/model.d.ts +0 -204
  251. package/dist/model/model.js +0 -1495
  252. package/dist/model/model.js.map +0 -1
  253. package/dist/model.util.d.ts +0 -204
  254. package/dist/model.util.js +0 -1495
  255. package/dist/model.util.js.map +0 -1
  256. package/dist/permission.util.d.ts +0 -38
  257. package/dist/permission.util.js +0 -91
  258. package/dist/permission.util.js.map +0 -1
  259. package/dist/registry.util.d.ts +0 -28
  260. package/dist/registry.util.js +0 -19
  261. package/dist/registry.util.js.map +0 -1
  262. package/dist/route.util.d.ts +0 -1
  263. package/dist/route.util.js +0 -12
  264. package/dist/route.util.js.map +0 -1
  265. package/dist/storage.util.d.ts +0 -56
  266. package/dist/storage.util.js +0 -82
  267. package/dist/storage.util.js.map +0 -1
  268. package/dist/validation.util.d.ts +0 -7
  269. package/dist/validation.util.js +0 -237
  270. package/dist/validation.util.js.map +0 -1
  271. /package/dist/commands/make/{light-controller.d.ts → skalfa-controller.d.ts} +0 -0
  272. /package/dist/commands/make/{light-model.d.ts → skalfa-model.d.ts} +0 -0
@@ -1,240 +1,125 @@
1
- import fs from "fs";
2
- import path from "path";
3
- import "elysia";
4
- import { Elysia, Context } from "elysia";
5
- import { validate, logger, KeyPermission, ValidationRules, ValidationRule } from "@utils";
6
- import { db } from "@skalfa/skalfa-orm";
7
-
8
-
9
-
10
- declare module "elysia" {
11
- interface ControllerContext extends Context {
12
- getQuery : {
13
- paginate : number;
14
- page : number;
15
- sort : string[];
16
- filter : Record<string, string>;
17
- search : string;
18
- searchable : string[];
19
- selectable : string[];
20
- selectableOption : string[];
21
- expand : string[];
22
- };
23
-
24
- responseData : (
25
- data : any[],
26
- totalRow ?: number,
27
- message ?: string,
28
- columns ?: string[],
29
- access ?: string[]
30
- ) => {
31
- status : number;
32
- body : any
33
- };
34
-
35
- validation : <T extends object>(rules: Partial<Record<keyof T | string, ValidationRule[] | string>>) => any;
36
- responseError : (error: any, section?: string, message?: string, debug?: boolean) => any;
37
- responseErrorValidation : (errors: Record<string, string[]>) => any;
38
- responseSaved : (data: any, message?: string) => any;
39
- responseSuccess : (data: any, message?: string) => any;
40
- responseForbidden : (message?: string) => any;
41
- uploadFile : (file: File, folder?: string) => Promise<string>;
42
- deleteFile : (filePath: string) => void;
43
- user ?: any
44
- permissions ?: KeyPermission[],
45
- payload : Record<string, any>
46
- }
47
- }
48
-
49
- export type ValidationRulesFor<T> = Partial<
50
- Record<keyof T | string, ValidationRule[] | string>
51
- >
52
-
53
-
54
- export const controller = (app: Elysia) => app.derive(({ query, body, status }) => ({
55
-
56
- // =====================================>
57
- // ## Basic fetching data query
58
- // =====================================>
59
- getQuery: {
60
- page : query.page ? Number(query.page) : 1,
61
- paginate : query.paginate ? Number(query.paginate) : 10,
62
- search : query.search ? query.search : "",
63
- sort : query.sort ? JSON.parse(query.sort) : ["created_at desc"],
64
- filter : query.filter ? JSON.parse(query.filter) : [],
65
- searchable : query.searchable ? JSON.parse(query.searchable) : [],
66
- selectable : query.selectable ? JSON.parse(query.selectable) : [],
67
- selectableOption : query.selectableOption ? JSON.parse(query.selectableOption) : [],
68
- expand : query.expand ? JSON.parse(query.expand) : [],
69
- },
70
-
71
-
72
-
73
- // ===================================>
74
- // ## Validation request body
75
- // ===================================>
76
- validation: async <T extends object>(
77
- rules: Partial<Record<keyof T | string, ValidationRules[] | string>>
78
- ) => {
79
- const result = await validate(
80
- body as Record<string, any>,
81
- rules as ValidationRules
82
- )
83
-
84
- if (!result.valid) {
85
- throw status(422, {
86
- message: "Error: Unprocessable Entity!",
87
- errors: result.errors,
88
- })
89
- }
90
- },
91
-
92
-
93
-
94
-
95
- // ====================================>
96
- // ## Response error validation
97
- // ====================================>
98
- responseErrorValidation: (errors: Record<string, string[]>) => {
99
- throw status(422, {
100
- message: "Error: Unprocessable Entity!",
101
- errors: errors,
102
- })
103
- },
104
-
105
-
106
-
107
- // ====================================>
108
- // ## Response error
109
- // ====================================>
110
- responseError: (error: any, section?: string, message?: string, debug = (process.env.APP_DEBUG || true)) => {
111
- logger.error(`Error: ${error}`, { error: error, feature: section })
112
-
113
- if (debug) {
114
- throw status(500, {
115
- message : message ?? "Error: Server Side Having Problem!",
116
- error : error?.message ?? "unknown",
117
- section : section ?? "unknown",
118
- })
119
- }
120
-
121
- throw status(500, {
122
- message: message ?? "Error: Server Side Having Problem!"
123
- })
124
- },
125
-
126
-
127
- // ====================================>
128
- // ## Response Forbidden
129
- // ====================================>
130
- responseForbidden: (message?: string) => {
131
- throw status(403, {
132
- message: message ?? "Access Forbidden!"
133
- })
134
- },
135
-
136
-
137
- // ====================================>
138
- // ## Response record
139
- // ====================================>
140
- responseData: (data: any[], totalRow?: number, message?: string) => {
141
- throw status(200, {
142
- message : message ?? (data.length ? "Success" : "Empty data"),
143
- data : data ?? [],
144
- total_row : totalRow ?? null,
145
- });
146
- },
147
-
148
-
149
-
150
- // ===================================>
151
- // ## Response success
152
- // ===================================>
153
- responseSuccess: (data: any, message?: string, code?: 200 | 201) => {
154
- throw status(code || 200, {
155
- message : message ?? "Success",
156
- data : data ?? [],
157
- })
158
- },
159
-
160
-
161
-
162
- // ===================================>
163
- // ## Response saved record
164
- // ===================================>
165
- responseSaved: (data: any, message?: string) => {
166
- throw status(201, {
167
- message : message ?? "Success",
168
- data : data ?? [],
169
- })
170
- },
171
-
172
-
173
-
174
- // ===================================>
175
- // ## Upload file
176
- // ===================================>
177
- uploadFile: async (file: File, folder = "uploads", options?: { disk?: "public" | "private", owner_id?: number, permissions?: { user_id?: number; role_id?: number }[]}): Promise<string> => {
178
- const disk = options?.disk ?? "public"
179
-
180
- const dir = path.resolve("storage", disk, folder);
181
- if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
182
-
183
- const fileName = `${Date.now().toString(36)}${Math.random().toString(36).substring(2, 18)}${path.extname(file.name).toLowerCase()}`;
184
- const filePath = path.join(dir, fileName);
185
-
186
- const buffer = Buffer.from(await file.arrayBuffer());
187
-
188
- fs.writeFileSync(filePath, buffer);
189
-
190
- const relativePath = `/${folder}/${fileName}`
191
-
192
- if(db && options) {
193
- const [storage] = await db("storages").insert({
194
- user_id : options?.owner_id ?? null,
195
- disk : disk,
196
- path : relativePath,
197
- filename : file.name,
198
- filetype : file.type,
199
- filesize : buffer.length,
200
- created_at : new Date(),
201
- }).returning(["id"])
202
-
203
- if (options?.permissions?.length) {
204
- const permissions = options.permissions.map(p => ({
205
- storage_id : storage.id,
206
- user_id : p.user_id ?? null,
207
- role_id : p.role_id ?? null,
208
- created_at : new Date(),
209
- }))
210
-
211
- await db("storage_permissions").insert(permissions)
212
- }
213
- }
214
-
215
-
216
- return relativePath
217
- },
218
-
219
-
220
-
221
- // ==================================>
222
- // ## Delete File
223
- // ==================================>
224
- deleteFile: async (filePath: string) => {
225
- if (fs.existsSync(filePath)) {
226
- if (db) {
227
- const record = await db("storages").where("path", filePath).first()
228
-
229
- if(record) {
230
- await db("storages").where("id", record.id).delete()
231
- await db("storage_permissions").where("storage_id", record.id).delete()
232
- }
233
- }
234
-
235
- fs.unlinkSync(filePath); return true;
236
- }
237
-
238
- return false;
239
- },
1
+ import "elysia";
2
+ import { Elysia, Context } from "elysia";
3
+ import { validate, KeyPermission, ValidationRules, ValidationRule } from "@utils";
4
+ import { responseErrorValidation, responseError, responseForbidden, responseData, responseSuccess, responseSaved } from "./response";
5
+ import { uploadFile, deleteFile } from "./storage";
6
+
7
+ declare module "elysia" {
8
+ interface ControllerContext extends Context {
9
+ getQuery : {
10
+ paginate : number;
11
+ page : number;
12
+ sort : string[];
13
+ filter : Record<string, string>;
14
+ search : string;
15
+ searchable : string[];
16
+ selectable : string[];
17
+ selectableOption : string[];
18
+ expand : string[];
19
+ };
20
+
21
+ responseData : (
22
+ data : any[],
23
+ totalRow ?: number,
24
+ message ?: string,
25
+ columns ?: string[],
26
+ access ?: string[]
27
+ ) => {
28
+ status : number;
29
+ body : any
30
+ };
31
+
32
+ validation : <T extends object>(rules: Partial<Record<keyof T | string, ValidationRule[] | string>>) => any;
33
+ responseError : (error: any, section?: string, message?: string, debug?: boolean) => any;
34
+ responseErrorValidation : (errors: Record<string, string[]>) => any;
35
+ responseSaved : (data: any, message?: string) => any;
36
+ responseSuccess : (data: any, message?: string) => any;
37
+ responseForbidden : (message?: string) => any;
38
+ uploadFile : (file: File, folder?: string) => Promise<string>;
39
+ deleteFile : (filePath: string) => void;
40
+ user ?: any
41
+ permissions ?: KeyPermission[],
42
+ payload : Record<string, any>
43
+ }
44
+ }
45
+
46
+ export type ValidationRulesFor<T> = Partial<
47
+ Record<keyof T | string, ValidationRule[] | string>
48
+ >
49
+
50
+ export const controller = (app: Elysia) => app.derive(({ query, body, status }) => ({
51
+
52
+ // =====================================>
53
+ // ## Controller: basic fetching data query
54
+ // =====================================>
55
+ getQuery: {
56
+ page : query.page ? Number(query.page) : 1,
57
+ paginate : query.paginate ? Number(query.paginate) : 10,
58
+ search : query.search ? query.search : "",
59
+ sort : query.sort ? JSON.parse(query.sort) : ["created_at desc"],
60
+ filter : query.filter ? JSON.parse(query.filter) : [],
61
+ searchable : query.searchable ? JSON.parse(query.searchable) : [],
62
+ selectable : query.selectable ? JSON.parse(query.selectable) : [],
63
+ selectableOption : query.selectableOption ? JSON.parse(query.selectableOption) : [],
64
+ expand : query.expand ? JSON.parse(query.expand) : [],
65
+ },
66
+
67
+ // =====================================>
68
+ // ## Controller: validation request body
69
+ // =====================================>
70
+ validation: async <T extends object>(
71
+ rules: Partial<Record<keyof T | string, ValidationRules[] | string>>
72
+ ) => {
73
+ const result = await validate(
74
+ body as Record<string, any>,
75
+ rules as ValidationRules
76
+ )
77
+
78
+ if (!result.valid) {
79
+ throw status(422, {
80
+ message: "Error: Unprocessable Entity!",
81
+ errors: result.errors,
82
+ })
83
+ }
84
+ },
85
+
86
+ // =====================================>
87
+ // ## Controller: response error validation
88
+ // =====================================>
89
+ responseErrorValidation: (errors: Record<string, string[]>) => responseErrorValidation(status, errors),
90
+
91
+ // =====================================>
92
+ // ## Controller: response error
93
+ // =====================================>
94
+ responseError: (error: any, section?: string, message?: string, debug?: boolean) => responseError(status, error, section, message, debug),
95
+
96
+ // =====================================>
97
+ // ## Controller: response forbidden
98
+ // =====================================>
99
+ responseForbidden: (message?: string) => responseForbidden(status, message),
100
+
101
+ // =====================================>
102
+ // ## Controller: response record
103
+ // =====================================>
104
+ responseData: (data: any[], totalRow?: number, message?: string) => responseData(status, data, totalRow, message),
105
+
106
+ // =====================================>
107
+ // ## Controller: response success
108
+ // =====================================>
109
+ responseSuccess: (data: any, message?: string, code?: 200 | 201) => responseSuccess(status, data, message, code),
110
+
111
+ // =====================================>
112
+ // ## Controller: response saved record
113
+ // =====================================>
114
+ responseSaved: (data: any, message?: string) => responseSaved(status, data, message),
115
+
116
+ // =====================================>
117
+ // ## Controller: upload file
118
+ // =====================================>
119
+ uploadFile,
120
+
121
+ // =====================================>
122
+ // ## Controller: delete file
123
+ // =====================================>
124
+ deleteFile,
240
125
  }));
@@ -0,0 +1,78 @@
1
+ import { logger } from "@utils";
2
+
3
+
4
+
5
+ // ====================================>
6
+ // ## Response error validation
7
+ // ====================================>
8
+ export function responseErrorValidation(status: any, errors: Record<string, string[]>) {
9
+ throw status(422, {
10
+ message: "Error: Unprocessable Entity!",
11
+ errors: errors,
12
+ });
13
+ }
14
+
15
+ // ====================================>
16
+ // ## Response error
17
+ // ====================================>
18
+ export function responseError(
19
+ status: any,
20
+ error: any,
21
+ section?: string,
22
+ message?: string,
23
+ debug = (process.env.APP_DEBUG || true)
24
+ ) {
25
+ logger.error(`Error: ${error}`, { error: error, feature: section });
26
+
27
+ if (debug) {
28
+ throw status(500, {
29
+ message : message ?? "Error: Server Side Having Problem!",
30
+ error : error?.message ?? "unknown",
31
+ section : section ?? "unknown",
32
+ });
33
+ }
34
+
35
+ throw status(500, {
36
+ message: message ?? "Error: Server Side Having Problem!"
37
+ });
38
+ }
39
+
40
+ // ====================================>
41
+ // ## Response Forbidden
42
+ // ====================================>
43
+ export function responseForbidden(status: any, message?: string) {
44
+ throw status(403, {
45
+ message: message ?? "Access Forbidden!"
46
+ });
47
+ }
48
+
49
+ // ====================================>
50
+ // ## Response record
51
+ // ====================================>
52
+ export function responseData(status: any, data: any[], totalRow?: number, message?: string) {
53
+ throw status(200, {
54
+ message : message ?? (data.length ? "Success" : "Empty data"),
55
+ data : data ?? [],
56
+ total_row : totalRow ?? null,
57
+ });
58
+ }
59
+
60
+ // ===================================>
61
+ // ## Response success
62
+ // ===================================>
63
+ export function responseSuccess(status: any, data: any, message?: string, code?: 200 | 201) {
64
+ throw status(code || 200, {
65
+ message : message ?? "Success",
66
+ data : data ?? [],
67
+ });
68
+ }
69
+
70
+ // ===================================>
71
+ // ## Response saved record
72
+ // ===================================>
73
+ export function responseSaved(status: any, data: any, message?: string) {
74
+ throw status(201, {
75
+ message : message ?? "Success",
76
+ data : data ?? [],
77
+ });
78
+ }
@@ -0,0 +1,78 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { db } from "@skalfa/skalfa-orm";
4
+
5
+
6
+
7
+ // ===================================>
8
+ // ## Upload file
9
+ // ===================================>
10
+ export async function uploadFile(
11
+ file: File,
12
+ folder = "uploads",
13
+ options?: {
14
+ disk?: "public" | "private";
15
+ owner_id?: number;
16
+ permissions?: { user_id?: number; role_id?: number }[];
17
+ }
18
+ ): Promise<string> {
19
+ const disk = options?.disk ?? "public";
20
+
21
+ const dir = path.resolve("storage", disk, folder);
22
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
23
+
24
+ const fileName = `${Date.now().toString(36)}${Math.random().toString(36).substring(2, 18)}${path.extname(file.name).toLowerCase()}`;
25
+ const filePath = path.join(dir, fileName);
26
+
27
+ const buffer = Buffer.from(await file.arrayBuffer());
28
+
29
+ fs.writeFileSync(filePath, buffer);
30
+
31
+ const relativePath = `/${folder}/${fileName}`;
32
+
33
+ if (db && options) {
34
+ const [storage] = await db("storages").insert({
35
+ user_id : options?.owner_id ?? null,
36
+ disk : disk,
37
+ path : relativePath,
38
+ filename : file.name,
39
+ filetype : file.type,
40
+ filesize : buffer.length,
41
+ created_at : new Date(),
42
+ }).returning(["id"]);
43
+
44
+ if (options?.permissions?.length) {
45
+ const permissions = options.permissions.map(p => ({
46
+ storage_id : storage.id,
47
+ user_id : p.user_id ?? null,
48
+ role_id : p.role_id ?? null,
49
+ created_at : new Date(),
50
+ }));
51
+
52
+ await db("storage_permissions").insert(permissions);
53
+ }
54
+ }
55
+
56
+ return relativePath;
57
+ }
58
+
59
+ // ==================================>
60
+ // ## Delete File
61
+ // ==================================>
62
+ export async function deleteFile(filePath: string): Promise<boolean> {
63
+ if (fs.existsSync(filePath)) {
64
+ if (db) {
65
+ const record = await db("storages").where("path", filePath).first();
66
+
67
+ if (record) {
68
+ await db("storages").where("id", record.id).delete();
69
+ await db("storage_permissions").where("storage_id", record.id).delete();
70
+ }
71
+ }
72
+
73
+ fs.unlinkSync(filePath);
74
+ return true;
75
+ }
76
+
77
+ return false;
78
+ }