@skalfa/skalfa-api-core 1.0.2

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 (249) hide show
  1. package/.github/workflows/publish.yml +40 -0
  2. package/dist/auth/auth.d.ts +19 -0
  3. package/dist/auth/auth.js +227 -0
  4. package/dist/auth/auth.js.map +1 -0
  5. package/dist/auth/index.d.ts +1 -0
  6. package/dist/auth/index.js +2 -0
  7. package/dist/auth/index.js.map +1 -0
  8. package/dist/auth.util.d.ts +19 -0
  9. package/dist/auth.util.js +183 -0
  10. package/dist/auth.util.js.map +1 -0
  11. package/dist/commands/cli.d.ts +1 -0
  12. package/dist/commands/cli.js +78 -0
  13. package/dist/commands/cli.js.map +1 -0
  14. package/dist/commands/make/basic-controller.d.ts +2 -0
  15. package/dist/commands/make/basic-controller.js +40 -0
  16. package/dist/commands/make/basic-controller.js.map +1 -0
  17. package/dist/commands/make/basic-migration.d.ts +5 -0
  18. package/dist/commands/make/basic-migration.js +60 -0
  19. package/dist/commands/make/basic-migration.js.map +1 -0
  20. package/dist/commands/make/basic-model.d.ts +2 -0
  21. package/dist/commands/make/basic-model.js +25 -0
  22. package/dist/commands/make/basic-model.js.map +1 -0
  23. package/dist/commands/make/basic-seeder.d.ts +3 -0
  24. package/dist/commands/make/basic-seeder.js +32 -0
  25. package/dist/commands/make/basic-seeder.js.map +1 -0
  26. package/dist/commands/make/blueprint.d.ts +2 -0
  27. package/dist/commands/make/blueprint.js +29 -0
  28. package/dist/commands/make/blueprint.js.map +1 -0
  29. package/dist/commands/make/da-migration.d.ts +5 -0
  30. package/dist/commands/make/da-migration.js +60 -0
  31. package/dist/commands/make/da-migration.js.map +1 -0
  32. package/dist/commands/make/light-controller.d.ts +3 -0
  33. package/dist/commands/make/light-controller.js +54 -0
  34. package/dist/commands/make/light-controller.js.map +1 -0
  35. package/dist/commands/make/light-model.d.ts +3 -0
  36. package/dist/commands/make/light-model.js +50 -0
  37. package/dist/commands/make/light-model.js.map +1 -0
  38. package/dist/commands/make/mail.d.ts +2 -0
  39. package/dist/commands/make/mail.js +41 -0
  40. package/dist/commands/make/mail.js.map +1 -0
  41. package/dist/commands/make/notification.d.ts +2 -0
  42. package/dist/commands/make/notification.js +33 -0
  43. package/dist/commands/make/notification.js.map +1 -0
  44. package/dist/commands/make/queue.d.ts +2 -0
  45. package/dist/commands/make/queue.js +35 -0
  46. package/dist/commands/make/queue.js.map +1 -0
  47. package/dist/commands/runner/barrels.d.ts +3 -0
  48. package/dist/commands/runner/barrels.js +78 -0
  49. package/dist/commands/runner/barrels.js.map +1 -0
  50. package/dist/commands/runner/blueprint/controller-generation.d.ts +1 -0
  51. package/dist/commands/runner/blueprint/controller-generation.js +147 -0
  52. package/dist/commands/runner/blueprint/controller-generation.js.map +1 -0
  53. package/dist/commands/runner/blueprint/documentation-generation.d.ts +6 -0
  54. package/dist/commands/runner/blueprint/documentation-generation.js +337 -0
  55. package/dist/commands/runner/blueprint/documentation-generation.js.map +1 -0
  56. package/dist/commands/runner/blueprint/migration-generation.d.ts +1 -0
  57. package/dist/commands/runner/blueprint/migration-generation.js +120 -0
  58. package/dist/commands/runner/blueprint/migration-generation.js.map +1 -0
  59. package/dist/commands/runner/blueprint/model-generation.d.ts +1 -0
  60. package/dist/commands/runner/blueprint/model-generation.js +122 -0
  61. package/dist/commands/runner/blueprint/model-generation.js.map +1 -0
  62. package/dist/commands/runner/blueprint/runner.d.ts +23 -0
  63. package/dist/commands/runner/blueprint/runner.js +139 -0
  64. package/dist/commands/runner/blueprint/runner.js.map +1 -0
  65. package/dist/commands/runner/blueprint/seeder-generation.d.ts +1 -0
  66. package/dist/commands/runner/blueprint/seeder-generation.js +40 -0
  67. package/dist/commands/runner/blueprint/seeder-generation.js.map +1 -0
  68. package/dist/commands/runner/da-migration.d.ts +39 -0
  69. package/dist/commands/runner/da-migration.js +262 -0
  70. package/dist/commands/runner/da-migration.js.map +1 -0
  71. package/dist/commands/runner/migration.d.ts +11 -0
  72. package/dist/commands/runner/migration.js +188 -0
  73. package/dist/commands/runner/migration.js.map +1 -0
  74. package/dist/commands/runner/seeder.d.ts +3 -0
  75. package/dist/commands/runner/seeder.js +40 -0
  76. package/dist/commands/runner/seeder.js.map +1 -0
  77. package/dist/commands/stubs/index.d.ts +14 -0
  78. package/dist/commands/stubs/index.js +277 -0
  79. package/dist/commands/stubs/index.js.map +1 -0
  80. package/dist/context/context.d.ts +7 -0
  81. package/dist/context/context.js +11 -0
  82. package/dist/context/context.js.map +1 -0
  83. package/dist/context/index.d.ts +1 -0
  84. package/dist/context/index.js +2 -0
  85. package/dist/context/index.js.map +1 -0
  86. package/dist/context.util.d.ts +7 -0
  87. package/dist/context.util.js +11 -0
  88. package/dist/context.util.js.map +1 -0
  89. package/dist/controller/controller.d.ts +118 -0
  90. package/dist/controller/controller.js +147 -0
  91. package/dist/controller/controller.js.map +1 -0
  92. package/dist/controller/index.d.ts +1 -0
  93. package/dist/controller/index.js +2 -0
  94. package/dist/controller/index.js.map +1 -0
  95. package/dist/controller.util.d.ts +118 -0
  96. package/dist/controller.util.js +144 -0
  97. package/dist/controller.util.js.map +1 -0
  98. package/dist/conversion/conversion.d.ts +8 -0
  99. package/dist/conversion/conversion.js +52 -0
  100. package/dist/conversion/conversion.js.map +1 -0
  101. package/dist/conversion/index.d.ts +1 -0
  102. package/dist/conversion/index.js +2 -0
  103. package/dist/conversion/index.js.map +1 -0
  104. package/dist/conversion.util.d.ts +8 -0
  105. package/dist/conversion.util.js +52 -0
  106. package/dist/conversion.util.js.map +1 -0
  107. package/dist/db/db.d.ts +84 -0
  108. package/dist/db/db.js +177 -0
  109. package/dist/db/db.js.map +1 -0
  110. package/dist/db/index.d.ts +1 -0
  111. package/dist/db/index.js +2 -0
  112. package/dist/db/index.js.map +1 -0
  113. package/dist/db.util.d.ts +84 -0
  114. package/dist/db.util.js +177 -0
  115. package/dist/db.util.js.map +1 -0
  116. package/dist/index.d.ts +21 -0
  117. package/dist/index.js +14 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/logger/index.d.ts +1 -0
  120. package/dist/logger/index.js +2 -0
  121. package/dist/logger/index.js.map +1 -0
  122. package/dist/logger/logger.d.ts +30 -0
  123. package/dist/logger/logger.js +126 -0
  124. package/dist/logger/logger.js.map +1 -0
  125. package/dist/logger.util.d.ts +30 -0
  126. package/dist/logger.util.js +126 -0
  127. package/dist/logger.util.js.map +1 -0
  128. package/dist/mail/index.d.ts +1 -0
  129. package/dist/mail/index.js +2 -0
  130. package/dist/mail/index.js.map +1 -0
  131. package/dist/mail/mail.d.ts +21 -0
  132. package/dist/mail/mail.js +53 -0
  133. package/dist/mail/mail.js.map +1 -0
  134. package/dist/mail.util.d.ts +21 -0
  135. package/dist/mail.util.js +53 -0
  136. package/dist/mail.util.js.map +1 -0
  137. package/dist/middleware/index.d.ts +1 -0
  138. package/dist/middleware/index.js +2 -0
  139. package/dist/middleware/index.js.map +1 -0
  140. package/dist/middleware/middleware.d.ts +263 -0
  141. package/dist/middleware/middleware.js +233 -0
  142. package/dist/middleware/middleware.js.map +1 -0
  143. package/dist/middleware.util.d.ts +263 -0
  144. package/dist/middleware.util.js +233 -0
  145. package/dist/middleware.util.js.map +1 -0
  146. package/dist/model/index.d.ts +3 -0
  147. package/dist/model/index.js +4 -0
  148. package/dist/model/index.js.map +1 -0
  149. package/dist/model/model.d.ts +204 -0
  150. package/dist/model/model.js +1495 -0
  151. package/dist/model/model.js.map +1 -0
  152. package/dist/model.util.d.ts +204 -0
  153. package/dist/model.util.js +1495 -0
  154. package/dist/model.util.js.map +1 -0
  155. package/dist/permission/index.d.ts +1 -0
  156. package/dist/permission/index.js +2 -0
  157. package/dist/permission/index.js.map +1 -0
  158. package/dist/permission/permission.d.ts +38 -0
  159. package/dist/permission/permission.js +91 -0
  160. package/dist/permission/permission.js.map +1 -0
  161. package/dist/permission.util.d.ts +38 -0
  162. package/dist/permission.util.js +91 -0
  163. package/dist/permission.util.js.map +1 -0
  164. package/dist/registry/index.d.ts +1 -0
  165. package/dist/registry/index.js +2 -0
  166. package/dist/registry/index.js.map +1 -0
  167. package/dist/registry/registry.d.ts +28 -0
  168. package/dist/registry/registry.js +19 -0
  169. package/dist/registry/registry.js.map +1 -0
  170. package/dist/registry.util.d.ts +28 -0
  171. package/dist/registry.util.js +19 -0
  172. package/dist/registry.util.js.map +1 -0
  173. package/dist/route/index.d.ts +1 -0
  174. package/dist/route/index.js +2 -0
  175. package/dist/route/index.js.map +1 -0
  176. package/dist/route/route.d.ts +1 -0
  177. package/dist/route/route.js +12 -0
  178. package/dist/route/route.js.map +1 -0
  179. package/dist/route.util.d.ts +1 -0
  180. package/dist/route.util.js +12 -0
  181. package/dist/route.util.js.map +1 -0
  182. package/dist/storage/index.d.ts +1 -0
  183. package/dist/storage/index.js +2 -0
  184. package/dist/storage/index.js.map +1 -0
  185. package/dist/storage/storage.d.ts +56 -0
  186. package/dist/storage/storage.js +86 -0
  187. package/dist/storage/storage.js.map +1 -0
  188. package/dist/storage.util.d.ts +56 -0
  189. package/dist/storage.util.js +82 -0
  190. package/dist/storage.util.js.map +1 -0
  191. package/dist/validation/index.d.ts +1 -0
  192. package/dist/validation/index.js +2 -0
  193. package/dist/validation/index.js.map +1 -0
  194. package/dist/validation/validation.d.ts +7 -0
  195. package/dist/validation/validation.js +245 -0
  196. package/dist/validation/validation.js.map +1 -0
  197. package/dist/validation.util.d.ts +7 -0
  198. package/dist/validation.util.js +237 -0
  199. package/dist/validation.util.js.map +1 -0
  200. package/package.json +34 -0
  201. package/src/auth/auth.ts +282 -0
  202. package/src/auth/index.ts +1 -0
  203. package/src/commands/cli.ts +89 -0
  204. package/src/commands/make/basic-controller.ts +49 -0
  205. package/src/commands/make/basic-migration.ts +89 -0
  206. package/src/commands/make/basic-model.ts +32 -0
  207. package/src/commands/make/basic-seeder.ts +38 -0
  208. package/src/commands/make/blueprint.ts +36 -0
  209. package/src/commands/make/da-migration.ts +90 -0
  210. package/src/commands/make/light-controller.ts +67 -0
  211. package/src/commands/make/light-model.ts +61 -0
  212. package/src/commands/make/mail.ts +51 -0
  213. package/src/commands/make/notification.ts +43 -0
  214. package/src/commands/make/queue.ts +45 -0
  215. package/src/commands/runner/barrels.ts +85 -0
  216. package/src/commands/runner/blueprint/controller-generation.ts +194 -0
  217. package/src/commands/runner/blueprint/documentation-generation.ts +463 -0
  218. package/src/commands/runner/blueprint/migration-generation.ts +153 -0
  219. package/src/commands/runner/blueprint/model-generation.ts +149 -0
  220. package/src/commands/runner/blueprint/runner.ts +181 -0
  221. package/src/commands/runner/blueprint/seeder-generation.ts +55 -0
  222. package/src/commands/runner/da-migration.ts +333 -0
  223. package/src/commands/runner/migration.ts +245 -0
  224. package/src/commands/runner/seeder.ts +44 -0
  225. package/src/commands/stubs/index.ts +289 -0
  226. package/src/context/context.ts +17 -0
  227. package/src/context/index.ts +1 -0
  228. package/src/controller/controller.ts +240 -0
  229. package/src/controller/index.ts +1 -0
  230. package/src/conversion/conversion.ts +65 -0
  231. package/src/conversion/index.ts +1 -0
  232. package/src/index.ts +22 -0
  233. package/src/logger/index.ts +1 -0
  234. package/src/logger/logger.ts +177 -0
  235. package/src/mail/index.ts +1 -0
  236. package/src/mail/mail.ts +86 -0
  237. package/src/middleware/index.ts +1 -0
  238. package/src/middleware/middleware.ts +289 -0
  239. package/src/permission/index.ts +1 -0
  240. package/src/permission/permission.ts +136 -0
  241. package/src/registry/index.ts +1 -0
  242. package/src/registry/registry.ts +37 -0
  243. package/src/route/index.ts +1 -0
  244. package/src/route/route.ts +12 -0
  245. package/src/storage/index.ts +1 -0
  246. package/src/storage/storage.ts +107 -0
  247. package/src/validation/index.ts +1 -0
  248. package/src/validation/validation.ts +346 -0
  249. package/tsconfig.json +23 -0
@@ -0,0 +1,289 @@
1
+ export const basicControllerStub = `import type { ControllerContext } from "elysia"
2
+
3
+ export class {{ name }} {
4
+ // ========================================>
5
+ // ## Display a listing of the resource.
6
+ // ========================================>
7
+ static async index(c: ControllerContext) {
8
+ // something amazing
9
+ }
10
+
11
+
12
+ // =============================================>
13
+ // ## Store a newly created resource.
14
+ // =============================================>
15
+ static async store(c: ControllerContext) {
16
+ // something amazing
17
+ }
18
+
19
+
20
+ // ============================================>
21
+ // ## Update the specified resource.
22
+ // ============================================>
23
+ static async update(c: ControllerContext) {
24
+ // something amazing
25
+ }
26
+
27
+
28
+ // ===============================================>
29
+ // ## Remove the specified resource.
30
+ // ===============================================>
31
+ static async destroy(c: ControllerContext) {
32
+ // something amazing
33
+ }
34
+ }`;
35
+
36
+ export const basicMigrationStub = `import type { Knex } from "knex"
37
+
38
+ export async function up(knex: Knex): Promise<void> {
39
+ await knex.schema.createTable("{{ tableName }}", (table) => {
40
+ table.bigIncrements('id').primary()
41
+ // your table schema
42
+ table.timestamps(true, true)
43
+ table.softDelete()
44
+ })
45
+ }`;
46
+
47
+ export const basicModelStub = `import { Model } from '@utils'
48
+
49
+ export class {{ name }} extends Model {
50
+ // something amazing
51
+ }`;
52
+
53
+ export const basicSeederStub = `import { {{ model }} } from "@models";
54
+
55
+ export default async function {{ name }}() {
56
+ // =========================>
57
+ // ## Seed the application's database
58
+ // =========================>
59
+
60
+ await {{ model }}.query().insert([]);
61
+ }
62
+ `;
63
+
64
+ export const blueprintStub = `[
65
+ {
66
+ "model" : "",
67
+ "schema" : {},
68
+ "relations": {},
69
+ "controllers": {},
70
+ "migrations" : true,
71
+ "seeders" : [],
72
+ "documentation": true
73
+ }
74
+ ]`;
75
+
76
+ export const daMigrationStub = `import { DAMigration } from "@utils"
77
+
78
+ export default class {{ className }} extends DAMigration {
79
+ async up() {
80
+ await this.createTable("{{ tableName }}",(table) => {
81
+ table.uuid()
82
+ }, {
83
+ engine: "MergeTree",
84
+ })
85
+ }
86
+ }
87
+ `;
88
+
89
+ export const lightControllerStub = `{{ marker }}
90
+ import type { ControllerContext } from "elysia"
91
+ import { permission } from '@utils'
92
+ import { {{ model }} } from '@models'
93
+
94
+
95
+
96
+ // ========================================>
97
+ // ## Permission of the resource.
98
+ // ========================================>
99
+ const p = permission.register({
100
+ "{{ permission_code }}": {
101
+ name: "{{ permission_name }}",
102
+ accesses: {
103
+ "00": "Melihat",
104
+ "01": "Membuat",
105
+ "02": "Mengubah",
106
+ "03": "Menghapus",
107
+ }
108
+ }
109
+ })
110
+
111
+
112
+
113
+ export class {{ name }} {
114
+ // ========================================>
115
+ // ## Display a listing of the resource.
116
+ // ========================================>
117
+ static async index(c: ControllerContext) {
118
+ p.have("{{ permission_code }}.00").guard(c)
119
+
120
+ const { data, total } = await {{ model }}.query().resolve(c)
121
+
122
+ c.responseData(data, total)
123
+ }
124
+
125
+
126
+ // =============================================>
127
+ // ## Store a newly created resource.
128
+ // =============================================>
129
+ static async store(c: ControllerContext) {
130
+ p.have("{{ permission_code }}.01").guard(c)
131
+
132
+ c.validation<{{ model }}>({{{ validations }}})
133
+
134
+ let record = {}
135
+
136
+ try {
137
+ record = await (new {{ model }}).pump(c.payload)
138
+ } catch (err) {
139
+ c.responseError(err as Error, "Create {{ model }}")
140
+ }
141
+
142
+ c.responseSaved(record)
143
+ }
144
+
145
+
146
+ // ============================================>
147
+ // ## Update the specified resource.
148
+ // ============================================>
149
+ static async update(c: ControllerContext) {
150
+ p.have("{{ permission_code }}.02").guard(c)
151
+
152
+ const record = await {{ model }}.query().findOrNotFound(c.params.id)
153
+
154
+ c.validation<{{ model }}>({{{ validations }}})
155
+
156
+ try {
157
+ await record.pump(c.payload)
158
+ } catch (err) {
159
+ c.responseError(err as Error, "Update {{ model }}")
160
+ }
161
+
162
+ c.responseSaved(record)
163
+ }
164
+
165
+
166
+ // ===============================================>
167
+ // ## Remove the specified resource.
168
+ // ===============================================>
169
+ static async destroy(c: ControllerContext) {
170
+ p.have("{{ permission_code }}.03").guard(c)
171
+
172
+ const record = await {{ model }}.query().findOrNotFound(c.params.id)
173
+
174
+ try {
175
+ await record.delete()
176
+ } catch (err) {
177
+ c.responseError(err as Error, "Delete {{ model }}")
178
+ }
179
+
180
+ c.responseSuccess(record)
181
+ }
182
+ }
183
+ `;
184
+
185
+ export const lightMigrationStub = `{{ marker }}
186
+ import type { Knex } from "knex"
187
+
188
+ export async function up(knex: Knex): Promise<void> {
189
+ await knex.schema.createTable("{{ tableName }}", (table) => {
190
+ table.bigIncrements('id').primary()
191
+ {{ schemas }}
192
+ table.timestamps(true, true)
193
+ table.softDelete()
194
+ })
195
+
196
+ {{ pivot }}
197
+ }`;
198
+
199
+ export const lightModelStub = `{{ marker }}
200
+ import { Model, SoftDelete{{ import_utils }} } from '@utils'
201
+ {{ import }}
202
+
203
+ export class {{ name }} extends Model {
204
+ // =====================>
205
+ // ## Field
206
+ // =====================>
207
+ {{ fields }}
208
+
209
+ @SoftDelete()
210
+ deleted_at!: Date
211
+
212
+
213
+ // =========================>
214
+ // ## Relations
215
+ // =========================>
216
+ {{ relations }}
217
+
218
+
219
+ // =====================>
220
+ // ## Attribute
221
+ // =====================>
222
+ {{ attributes }}
223
+
224
+
225
+ // =====================>
226
+ // ## Hook
227
+ // =====================>
228
+
229
+ }
230
+ `;
231
+
232
+ export const lightSeederStub = `{{ marker }}
233
+ import { {{ model }} } from "@models";
234
+
235
+ export default async function {{ name }}Seeder() {
236
+ // =========================>
237
+ // ## Seed the application's database
238
+ // =========================>
239
+
240
+ await (new {{ model }}).pump([
241
+ {{ seeders }}
242
+ ]);
243
+ }
244
+ `;
245
+
246
+ export const mailStub = `import { renderMailTemplate, sendMail } from "@utils"
247
+
248
+ export async function {{ name }}Mail(to: string) {
249
+ const content = renderMailTemplate("{{ name }}", {
250
+ title: "{{ title }}",
251
+ })
252
+
253
+ const send = await sendMail({
254
+ subject: "{{ title }}",
255
+ to: to,
256
+ content: content
257
+ })
258
+
259
+ return send;
260
+ }
261
+ `;
262
+
263
+ export const notificationStub = `import { queue } from "@utils";
264
+
265
+ export async function {{ name }}Notification(payload: Record<string,any>) {
266
+ await queue.add('notification', { payload })
267
+ }
268
+ `;
269
+
270
+ export const queueStub = `import { queue } from '@utils'
271
+
272
+ export const {{ name }}QueueWorker = () => {
273
+ queue.worker("{{ worker_name }}", async (payload) => {
274
+
275
+ })
276
+ }
277
+ `;
278
+
279
+ export const routeStub = `import { Elysia } from 'elysia'
280
+ import { api, middleware } from '@utils'
281
+ import {
282
+
283
+ } from '@controllers'
284
+
285
+ export const {{ name }}Routes = (app: Elysia) => app.group('/{{ path }}', (route) => {
286
+
287
+ return route;
288
+ })
289
+ `;
@@ -0,0 +1,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
+ 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
+ }
@@ -0,0 +1 @@
1
+ export * from "./context";
@@ -0,0 +1,240 @@
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
+ },
240
+ }));
@@ -0,0 +1 @@
1
+ export * from "./controller";
@@ -0,0 +1,65 @@
1
+ export const conversion = {
2
+
3
+ // =============================>
4
+ // ## Conversion: String formatter
5
+ // =============================>
6
+ strSnake(value: string, delimiter: string = "_"): string {
7
+ return toWords(value).join(delimiter)
8
+ },
9
+
10
+ strSlug(value: string, delimiter: string = "-"): string {
11
+ return toWords(value).join(delimiter);
12
+ },
13
+
14
+ strCamel(value: string, delimiter: string = ""): string {
15
+ return toWords(value).map((w, i) => i === 0 ? w : w[0].toUpperCase() + w.slice(1)).join(delimiter);
16
+ },
17
+
18
+ strPascal(value: string, delimiter: string = ""): string {
19
+ return toWords(value).map(w => w[0].toUpperCase() + w.slice(1)).join(delimiter);
20
+ },
21
+
22
+ strPlural(value: string): string {
23
+ const match = value.match(/^(.*?)([A-Za-z]+)$/)
24
+ if (!match) return value
25
+
26
+ const [, prefix, word] = match
27
+
28
+ if (word.endsWith("y") && !/[aeiou]y$/i.test(word)) {
29
+ return prefix + word.slice(0, -1) + "ies"
30
+ }
31
+
32
+ if (!word.endsWith("s")) return prefix + word + "s"
33
+
34
+ return value
35
+ },
36
+
37
+ strSingular(value: string): string {
38
+ const match = value.match(/^(.*?)([A-Za-z]+)$/)
39
+ if (!match) return value
40
+
41
+ const [, prefix, word] = match
42
+
43
+ if (word.endsWith("ies")) {
44
+ return prefix + word.slice(0, -3) + "y"
45
+ }
46
+
47
+ if (word.endsWith("s") && !word.endsWith("ss")) {
48
+ return prefix + word.slice(0, -1)
49
+ }
50
+
51
+ return value
52
+ }
53
+ };
54
+
55
+
56
+
57
+ function toWords(value: string): string[] {
58
+ return value
59
+ .replace(/([a-z0-9])([A-Z])/g, "$1 $2")
60
+ .replace(/[_\-\s]+/g, " ")
61
+ .trim()
62
+ .toLowerCase()
63
+ .split(" ")
64
+ .filter(Boolean)
65
+ }
@@ -0,0 +1 @@
1
+ export * from "./conversion";
package/src/index.ts ADDED
@@ -0,0 +1,22 @@
1
+ export * from "./auth";
2
+ export * from "./controller";
3
+ export * from "./conversion";
4
+ export * from "./context";
5
+ export * from "./middleware";
6
+ export * from "./permission";
7
+ export * from "./route";
8
+ export * from "./storage";
9
+ export * from "./validation";
10
+ export * from "./mail";
11
+ export * from "./logger";
12
+ export * from "./registry";
13
+ export * from "./commands/cli";
14
+
15
+ declare module "knex" {
16
+ namespace Knex {
17
+ interface CreateTableBuilder {
18
+ foreignIdFor(tableName: string, column?: string): Knex.ColumnBuilder;
19
+ softDelete(column?: string): Knex.ColumnBuilder;
20
+ }
21
+ }
22
+ }
@@ -0,0 +1 @@
1
+ export * from "./logger";