@skalfa/skalfa-api-core 1.0.3 → 1.0.8

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 (284) 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 +18 -27
  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/skalfa-controller.d.ts +3 -0
  68. package/dist/commands/make/{light-controller.js → skalfa-controller.js} +9 -9
  69. package/dist/commands/make/skalfa-controller.js.map +1 -0
  70. package/dist/commands/make/skalfa-model.d.ts +3 -0
  71. package/dist/commands/make/{light-model.js → skalfa-model.js} +11 -11
  72. package/dist/commands/make/skalfa-model.js.map +1 -0
  73. package/dist/commands/runner/barrels.js.map +1 -1
  74. package/dist/commands/runner/blueprint/controller-generation.js +2 -2
  75. package/dist/commands/runner/blueprint/controller-generation.js.map +1 -1
  76. package/dist/commands/runner/blueprint/documentation-generation.js.map +1 -1
  77. package/dist/commands/runner/blueprint/migration-generation.js +3 -3
  78. package/dist/commands/runner/blueprint/migration-generation.js.map +1 -1
  79. package/dist/commands/runner/blueprint/model-generation.js +2 -2
  80. package/dist/commands/runner/blueprint/model-generation.js.map +1 -1
  81. package/dist/commands/runner/blueprint/runner.js +7 -8
  82. package/dist/commands/runner/blueprint/runner.js.map +1 -1
  83. package/dist/commands/runner/blueprint/seeder-generation.js +3 -3
  84. package/dist/commands/runner/blueprint/seeder-generation.js.map +1 -1
  85. package/dist/commands/runner/da-migration.js +1 -2
  86. package/dist/commands/runner/da-migration.js.map +1 -1
  87. package/dist/commands/runner/generate-docs.d.ts +2 -0
  88. package/dist/commands/runner/generate-docs.js +400 -0
  89. package/dist/commands/runner/generate-docs.js.map +1 -0
  90. package/dist/commands/runner/migration.js +1 -1
  91. package/dist/commands/runner/migration.js.map +1 -1
  92. package/dist/commands/runner/seeder.js +1 -1
  93. package/dist/commands/runner/seeder.js.map +1 -1
  94. package/dist/commands/stubs/index.d.ts +4 -4
  95. package/dist/commands/stubs/index.js +4 -4
  96. package/dist/commands/stubs/index.js.map +1 -1
  97. package/dist/context/context.js +6 -0
  98. package/dist/context/context.js.map +1 -1
  99. package/dist/controller/controller.d.ts +17 -30
  100. package/dist/controller/controller.js +39 -121
  101. package/dist/controller/controller.js.map +1 -1
  102. package/dist/controller/response.d.ts +6 -0
  103. package/dist/controller/response.js +63 -0
  104. package/dist/controller/response.js.map +1 -0
  105. package/dist/controller/storage.d.ts +9 -0
  106. package/dist/controller/storage.js +56 -0
  107. package/dist/controller/storage.js.map +1 -0
  108. package/dist/conversion/conversion.d.ts +3 -0
  109. package/dist/conversion/conversion.js +28 -4
  110. package/dist/conversion/conversion.js.map +1 -1
  111. package/dist/conversion/date.d.ts +1 -0
  112. package/dist/conversion/date.js +77 -0
  113. package/dist/conversion/date.js.map +1 -0
  114. package/dist/index.d.ts +2 -0
  115. package/dist/index.js +2 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/logger/logger.js +33 -0
  118. package/dist/logger/logger.js.map +1 -1
  119. package/dist/mail/mail.js +6 -6
  120. package/dist/mail/mail.js.map +1 -1
  121. package/dist/middleware/access-log.d.ts +31 -0
  122. package/dist/middleware/access-log.js +13 -0
  123. package/dist/middleware/access-log.js.map +1 -0
  124. package/dist/middleware/auth.d.ts +37 -0
  125. package/dist/middleware/auth.js +16 -0
  126. package/dist/middleware/auth.js.map +1 -0
  127. package/dist/middleware/body-parse.d.ts +35 -0
  128. package/dist/middleware/body-parse.js +87 -0
  129. package/dist/middleware/body-parse.js.map +1 -0
  130. package/dist/middleware/context.d.ts +29 -0
  131. package/dist/middleware/context.js +8 -0
  132. package/dist/middleware/context.js.map +1 -0
  133. package/dist/middleware/cors.d.ts +31 -0
  134. package/dist/middleware/cors.js +27 -0
  135. package/dist/middleware/cors.js.map +1 -0
  136. package/dist/middleware/error-handler.d.ts +33 -0
  137. package/dist/middleware/error-handler.js +17 -0
  138. package/dist/middleware/error-handler.js.map +1 -0
  139. package/dist/middleware/middleware.d.ts +31 -10
  140. package/dist/middleware/middleware.js +41 -209
  141. package/dist/middleware/middleware.js.map +1 -1
  142. package/dist/middleware/private.d.ts +29 -0
  143. package/dist/middleware/private.js +8 -0
  144. package/dist/middleware/private.js.map +1 -0
  145. package/dist/middleware/rate-limiter.d.ts +32 -0
  146. package/dist/middleware/rate-limiter.js +30 -0
  147. package/dist/middleware/rate-limiter.js.map +1 -0
  148. package/dist/notification/index.d.ts +1 -0
  149. package/dist/notification/index.js +2 -0
  150. package/dist/notification/index.js.map +1 -0
  151. package/dist/notification/notification.d.ts +16 -0
  152. package/dist/notification/notification.js +64 -0
  153. package/dist/notification/notification.js.map +1 -0
  154. package/dist/permission/permission.js +9 -0
  155. package/dist/permission/permission.js.map +1 -1
  156. package/dist/registry/registry.d.ts +0 -6
  157. package/dist/registry/registry.js +6 -6
  158. package/dist/registry/registry.js.map +1 -1
  159. package/dist/storage/storage.d.ts +3 -3
  160. package/dist/storage/storage.js.map +1 -1
  161. package/dist/validation/validation.js +43 -51
  162. package/dist/validation/validation.js.map +1 -1
  163. package/package.json +4 -4
  164. package/src/auth/auth.ts +21 -252
  165. package/src/auth/create-access-token.ts +29 -0
  166. package/src/auth/create-user-mail-token.ts +24 -0
  167. package/src/auth/helpers/generate-agent-id.ts +8 -0
  168. package/src/auth/helpers/get-request-ip.ts +3 -0
  169. package/src/auth/helpers/get-user-permissions.ts +15 -0
  170. package/src/auth/helpers/index.ts +3 -0
  171. package/src/auth/list-user-sessions.ts +11 -0
  172. package/src/auth/revalidate-user-permissions-by-role.ts +13 -0
  173. package/src/auth/revalidate-user-permissions.ts +26 -0
  174. package/src/auth/revoke-access-token.ts +5 -0
  175. package/src/auth/verify-access-token.ts +56 -0
  176. package/src/auth/verify-user-mail-token.ts +24 -0
  177. package/src/commands/cli.ts +19 -29
  178. package/src/commands/make/basic-controller.ts +4 -2
  179. package/src/commands/make/basic-migration.ts +5 -3
  180. package/src/commands/make/basic-model.ts +3 -1
  181. package/src/commands/make/basic-seeder.ts +3 -1
  182. package/src/commands/make/blueprint.ts +3 -1
  183. package/src/commands/make/da-migration.ts +6 -5
  184. package/src/commands/make/mail.ts +4 -2
  185. package/src/commands/make/notification.ts +3 -1
  186. package/src/commands/make/queue.ts +3 -1
  187. package/src/commands/make/resource.ts +21 -0
  188. package/src/commands/make/{light-controller.ts → skalfa-controller.ts} +10 -8
  189. package/src/commands/make/{light-model.ts → skalfa-model.ts} +12 -10
  190. package/src/commands/runner/barrels.ts +4 -0
  191. package/src/commands/runner/blueprint/controller-generation.ts +4 -2
  192. package/src/commands/runner/blueprint/documentation-generation.ts +2 -0
  193. package/src/commands/runner/blueprint/migration-generation.ts +5 -3
  194. package/src/commands/runner/blueprint/model-generation.ts +4 -2
  195. package/src/commands/runner/blueprint/runner.ts +15 -8
  196. package/src/commands/runner/blueprint/seeder-generation.ts +5 -3
  197. package/src/commands/runner/da-migration.ts +3 -2
  198. package/src/commands/runner/generate-docs.ts +495 -0
  199. package/src/commands/runner/migration.ts +1 -1
  200. package/src/commands/runner/seeder.ts +1 -1
  201. package/src/commands/stubs/index.ts +4 -4
  202. package/src/context/context.ts +23 -17
  203. package/src/controller/controller.ts +124 -239
  204. package/src/controller/response.ts +78 -0
  205. package/src/controller/storage.ts +78 -0
  206. package/src/conversion/conversion.ts +90 -64
  207. package/src/conversion/date.ts +74 -0
  208. package/src/index.ts +2 -0
  209. package/src/logger/logger.ts +217 -176
  210. package/src/mail/mail.ts +85 -85
  211. package/src/middleware/access-log.ts +15 -0
  212. package/src/middleware/auth.ts +19 -0
  213. package/src/middleware/body-parse.ts +83 -0
  214. package/src/middleware/context.ts +11 -0
  215. package/src/middleware/cors.ts +31 -0
  216. package/src/middleware/error-handler.ts +20 -0
  217. package/src/middleware/middleware.ts +91 -288
  218. package/src/middleware/private.ts +8 -0
  219. package/src/middleware/rate-limiter.ts +41 -0
  220. package/src/notification/index.ts +1 -0
  221. package/src/notification/notification.ts +86 -0
  222. package/src/permission/permission.ts +140 -136
  223. package/src/registry/registry.ts +17 -15
  224. package/src/route/route.ts +11 -11
  225. package/src/storage/storage.ts +104 -106
  226. package/src/validation/validation.ts +322 -346
  227. package/dist/auth.util.d.ts +0 -19
  228. package/dist/auth.util.js +0 -183
  229. package/dist/auth.util.js.map +0 -1
  230. package/dist/commands/make/light-controller.d.ts +0 -3
  231. package/dist/commands/make/light-controller.js.map +0 -1
  232. package/dist/commands/make/light-model.d.ts +0 -3
  233. package/dist/commands/make/light-model.js.map +0 -1
  234. package/dist/context.util.d.ts +0 -7
  235. package/dist/context.util.js +0 -11
  236. package/dist/context.util.js.map +0 -1
  237. package/dist/controller.util.d.ts +0 -118
  238. package/dist/controller.util.js +0 -144
  239. package/dist/controller.util.js.map +0 -1
  240. package/dist/conversion.util.d.ts +0 -8
  241. package/dist/conversion.util.js +0 -52
  242. package/dist/conversion.util.js.map +0 -1
  243. package/dist/db/db.d.ts +0 -84
  244. package/dist/db/db.js +0 -177
  245. package/dist/db/db.js.map +0 -1
  246. package/dist/db/index.d.ts +0 -1
  247. package/dist/db/index.js +0 -2
  248. package/dist/db/index.js.map +0 -1
  249. package/dist/db.util.d.ts +0 -84
  250. package/dist/db.util.js +0 -177
  251. package/dist/db.util.js.map +0 -1
  252. package/dist/logger.util.d.ts +0 -30
  253. package/dist/logger.util.js +0 -126
  254. package/dist/logger.util.js.map +0 -1
  255. package/dist/mail.util.d.ts +0 -21
  256. package/dist/mail.util.js +0 -53
  257. package/dist/mail.util.js.map +0 -1
  258. package/dist/middleware.util.d.ts +0 -263
  259. package/dist/middleware.util.js +0 -233
  260. package/dist/middleware.util.js.map +0 -1
  261. package/dist/model/index.d.ts +0 -3
  262. package/dist/model/index.js +0 -4
  263. package/dist/model/index.js.map +0 -1
  264. package/dist/model/model.d.ts +0 -204
  265. package/dist/model/model.js +0 -1495
  266. package/dist/model/model.js.map +0 -1
  267. package/dist/model.util.d.ts +0 -204
  268. package/dist/model.util.js +0 -1495
  269. package/dist/model.util.js.map +0 -1
  270. package/dist/permission.util.d.ts +0 -38
  271. package/dist/permission.util.js +0 -91
  272. package/dist/permission.util.js.map +0 -1
  273. package/dist/registry.util.d.ts +0 -28
  274. package/dist/registry.util.js +0 -19
  275. package/dist/registry.util.js.map +0 -1
  276. package/dist/route.util.d.ts +0 -1
  277. package/dist/route.util.js +0 -12
  278. package/dist/route.util.js.map +0 -1
  279. package/dist/storage.util.d.ts +0 -56
  280. package/dist/storage.util.js +0 -82
  281. package/dist/storage.util.js.map +0 -1
  282. package/dist/validation.util.d.ts +0 -7
  283. package/dist/validation.util.js +0 -237
  284. package/dist/validation.util.js.map +0 -1
@@ -86,7 +86,7 @@ export default class {{ className }} extends DAMigration {
86
86
  }
87
87
  `;
88
88
 
89
- export const lightControllerStub = `{{ marker }}
89
+ export const skalfaControllerStub = `{{ marker }}
90
90
  import type { ControllerContext } from "elysia"
91
91
  import { permission } from '@utils'
92
92
  import { {{ model }} } from '@models'
@@ -182,7 +182,7 @@ export class {{ name }} {
182
182
  }
183
183
  `;
184
184
 
185
- export const lightMigrationStub = `{{ marker }}
185
+ export const skalfaMigrationStub = `{{ marker }}
186
186
  import type { Knex } from "knex"
187
187
 
188
188
  export async function up(knex: Knex): Promise<void> {
@@ -196,7 +196,7 @@ export async function up(knex: Knex): Promise<void> {
196
196
  {{ pivot }}
197
197
  }`;
198
198
 
199
- export const lightModelStub = `{{ marker }}
199
+ export const skalfaModelStub = `{{ marker }}
200
200
  import { Model, SoftDelete{{ import_utils }} } from '@utils'
201
201
  {{ import }}
202
202
 
@@ -229,7 +229,7 @@ export class {{ name }} extends Model {
229
229
  }
230
230
  `;
231
231
 
232
- export const lightSeederStub = `{{ marker }}
232
+ export const skalfaSeederStub = `{{ marker }}
233
233
  import { {{ model }} } from "@models";
234
234
 
235
235
  export default async function {{ name }}Seeder() {
@@ -1,17 +1,23 @@
1
- import { AsyncLocalStorage } from 'node:async_hooks'
2
-
3
- export type AppContext = {
4
- user_id?: number,
5
- }
6
-
7
- const storage = new AsyncLocalStorage<AppContext>()
8
-
9
- export const context = {
10
- run<T>(ctx: AppContext, fn: () => T) {
11
- return storage.run(ctx, fn)
12
- },
13
-
14
- get<K extends keyof AppContext>(key: K): AppContext[K] {
15
- return storage.getStore()?.[key]
16
- },
17
- }
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
2
+
3
+ export type AppContext = {
4
+ user_id ?: number,
5
+ }
6
+
7
+ const storage = new AsyncLocalStorage<AppContext>()
8
+
9
+ export const context = {
10
+ // =====================================>
11
+ // ## Context: run a function within context
12
+ // =====================================>
13
+ run<T>(ctx: AppContext, fn: () => T) {
14
+ return storage.run(ctx, fn)
15
+ },
16
+
17
+ // =====================================>
18
+ // ## Context: retrieve context property value
19
+ // =====================================>
20
+ get<K extends keyof AppContext>(key: K): AppContext[K] {
21
+ return storage.getStore()?.[key]
22
+ },
23
+ }
@@ -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
+ }