sonamu 0.4.14 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (348) hide show
  1. package/.swcrc +15 -0
  2. package/dist/api/base-frame.d.ts +8 -0
  3. package/dist/api/base-frame.d.ts.map +1 -0
  4. package/dist/api/base-frame.js +2 -0
  5. package/dist/api/base-frame.js.map +1 -0
  6. package/dist/api/caster.d.ts +5 -0
  7. package/dist/api/caster.d.ts.map +1 -0
  8. package/dist/api/caster.js +2 -0
  9. package/dist/api/caster.js.map +1 -0
  10. package/dist/api/code-converters.d.ts +23 -0
  11. package/dist/api/code-converters.d.ts.map +1 -0
  12. package/dist/api/code-converters.js +2 -0
  13. package/dist/api/code-converters.js.map +1 -0
  14. package/dist/api/context.d.ts +16 -0
  15. package/dist/api/context.d.ts.map +1 -0
  16. package/dist/api/context.js +2 -0
  17. package/dist/api/context.js.map +1 -0
  18. package/dist/api/decorators.d.ts +50 -0
  19. package/dist/api/decorators.d.ts.map +1 -0
  20. package/dist/api/decorators.js +2 -0
  21. package/dist/api/decorators.js.map +1 -0
  22. package/dist/api/index.d.ts +8 -0
  23. package/dist/api/index.d.ts.map +1 -0
  24. package/dist/api/index.js +2 -0
  25. package/dist/api/index.js.map +1 -0
  26. package/dist/api/sonamu.d.ts +83 -0
  27. package/dist/api/sonamu.d.ts.map +1 -0
  28. package/dist/api/sonamu.js +2 -0
  29. package/dist/api/sonamu.js.map +1 -0
  30. package/dist/api/sonamu.types.d.ts +30 -0
  31. package/dist/api/sonamu.types.d.ts.map +1 -0
  32. package/dist/api/sonamu.types.js +2 -0
  33. package/dist/api/sonamu.types.js.map +1 -0
  34. package/dist/bin/build-config.d.ts +5 -0
  35. package/dist/bin/build-config.d.ts.map +1 -0
  36. package/dist/bin/build-config.js +2 -0
  37. package/dist/bin/build-config.js.map +1 -0
  38. package/dist/bin/cli-wrapper.d.ts +2 -0
  39. package/dist/bin/cli-wrapper.d.ts.map +1 -0
  40. package/dist/bin/cli-wrapper.js +1 -38
  41. package/dist/bin/cli-wrapper.js.map +1 -1
  42. package/dist/bin/cli.d.ts +2 -2
  43. package/dist/bin/cli.d.ts.map +1 -0
  44. package/dist/bin/cli.js +1 -903
  45. package/dist/bin/cli.js.map +1 -1
  46. package/dist/database/_batch_update.d.ts +15 -0
  47. package/dist/database/_batch_update.d.ts.map +1 -0
  48. package/dist/database/_batch_update.js +2 -0
  49. package/dist/database/_batch_update.js.map +1 -0
  50. package/dist/database/base-model.d.ts +41 -0
  51. package/dist/database/base-model.d.ts.map +1 -0
  52. package/dist/database/base-model.js +2 -0
  53. package/dist/database/base-model.js.map +1 -0
  54. package/dist/database/code-generator.d.ts +13 -0
  55. package/dist/database/code-generator.d.ts.map +1 -0
  56. package/dist/database/code-generator.js +2 -0
  57. package/dist/database/code-generator.js.map +1 -0
  58. package/dist/database/db.d.ts +40 -0
  59. package/dist/database/db.d.ts.map +1 -0
  60. package/dist/database/db.js +2 -0
  61. package/dist/database/db.js.map +1 -0
  62. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +2 -0
  63. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +1 -0
  64. package/dist/database/knex-plugins/knex-on-duplicate-update.js +2 -0
  65. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +1 -0
  66. package/dist/database/puri-wrapper.d.ts +34 -0
  67. package/dist/database/puri-wrapper.d.ts.map +1 -0
  68. package/dist/database/puri-wrapper.js +2 -0
  69. package/dist/database/puri-wrapper.js.map +1 -0
  70. package/dist/database/puri.d.ts +83 -0
  71. package/dist/database/puri.d.ts.map +1 -0
  72. package/dist/database/puri.js +2 -0
  73. package/dist/database/puri.js.map +1 -0
  74. package/dist/database/puri.types.d.ts +60 -0
  75. package/dist/database/puri.types.d.ts.map +1 -0
  76. package/dist/database/puri.types.js +2 -0
  77. package/dist/database/puri.types.js.map +1 -0
  78. package/dist/database/transaction-context.d.ts +9 -0
  79. package/dist/database/transaction-context.d.ts.map +1 -0
  80. package/dist/database/transaction-context.js +2 -0
  81. package/dist/database/transaction-context.js.map +1 -0
  82. package/dist/database/types.d.ts +39 -0
  83. package/dist/database/types.d.ts.map +1 -0
  84. package/dist/database/types.js +2 -0
  85. package/dist/database/types.js.map +1 -0
  86. package/dist/database/upsert-builder.d.ts +34 -0
  87. package/dist/database/upsert-builder.d.ts.map +1 -0
  88. package/dist/database/upsert-builder.js +2 -0
  89. package/dist/database/upsert-builder.js.map +1 -0
  90. package/dist/entity/entity-manager.d.ts +32 -0
  91. package/dist/entity/entity-manager.d.ts.map +1 -0
  92. package/dist/entity/entity-manager.js +2 -0
  93. package/dist/entity/entity-manager.js.map +1 -0
  94. package/dist/entity/entity-utils.d.ts +61 -0
  95. package/dist/entity/entity-utils.d.ts.map +1 -0
  96. package/dist/entity/entity-utils.js +2 -0
  97. package/dist/entity/entity-utils.js.map +1 -0
  98. package/dist/entity/entity.d.ts +62 -0
  99. package/dist/entity/entity.d.ts.map +1 -0
  100. package/dist/entity/entity.js +2 -0
  101. package/dist/entity/entity.js.map +1 -0
  102. package/dist/entity/migrator.d.ts +135 -0
  103. package/dist/entity/migrator.d.ts.map +1 -0
  104. package/dist/entity/migrator.js +2 -0
  105. package/dist/entity/migrator.js.map +1 -0
  106. package/dist/exceptions/error-handler.d.ts +3 -0
  107. package/dist/exceptions/error-handler.d.ts.map +1 -0
  108. package/dist/exceptions/error-handler.js +2 -0
  109. package/dist/exceptions/error-handler.js.map +1 -0
  110. package/dist/exceptions/so-exceptions.d.ts +48 -0
  111. package/dist/exceptions/so-exceptions.d.ts.map +1 -0
  112. package/dist/exceptions/so-exceptions.js +2 -0
  113. package/dist/exceptions/so-exceptions.js.map +1 -0
  114. package/dist/file-storage/driver.d.ts +45 -0
  115. package/dist/file-storage/driver.d.ts.map +1 -0
  116. package/dist/file-storage/driver.js +2 -0
  117. package/dist/file-storage/driver.js.map +1 -0
  118. package/dist/file-storage/file-storage.d.ts +50 -0
  119. package/dist/file-storage/file-storage.d.ts.map +1 -0
  120. package/dist/file-storage/file-storage.js +2 -0
  121. package/dist/file-storage/file-storage.js.map +1 -0
  122. package/dist/index.d.ts +22 -813
  123. package/dist/index.d.ts.map +1 -0
  124. package/dist/index.js +1 -433
  125. package/dist/index.js.map +1 -1
  126. package/dist/migration/code-generation.d.ts +15 -0
  127. package/dist/migration/code-generation.d.ts.map +1 -0
  128. package/dist/migration/code-generation.js +2 -0
  129. package/dist/migration/code-generation.js.map +1 -0
  130. package/dist/migration/migration-set.d.ts +17 -0
  131. package/dist/migration/migration-set.d.ts.map +1 -0
  132. package/dist/migration/migration-set.js +2 -0
  133. package/dist/migration/migration-set.js.map +1 -0
  134. package/dist/migration/migrator.d.ts +130 -0
  135. package/dist/migration/migrator.d.ts.map +1 -0
  136. package/dist/migration/migrator.js +2 -0
  137. package/dist/migration/migrator.js.map +1 -0
  138. package/dist/migration/types.d.ts +52 -0
  139. package/dist/migration/types.d.ts.map +1 -0
  140. package/dist/migration/types.js +2 -0
  141. package/dist/migration/types.js.map +1 -0
  142. package/dist/smd/smd-manager.d.ts +28 -0
  143. package/dist/smd/smd-manager.d.ts.map +1 -0
  144. package/dist/smd/smd-manager.js +2 -0
  145. package/dist/smd/smd-manager.js.map +1 -0
  146. package/dist/smd/smd.d.ts +40 -0
  147. package/dist/smd/smd.d.ts.map +1 -0
  148. package/dist/smd/smd.js +2 -0
  149. package/dist/smd/smd.js.map +1 -0
  150. package/dist/syncer/index.d.ts +2 -0
  151. package/dist/syncer/index.d.ts.map +1 -0
  152. package/dist/syncer/index.js +2 -0
  153. package/dist/syncer/index.js.map +1 -0
  154. package/dist/syncer/syncer.d.ts +127 -0
  155. package/dist/syncer/syncer.d.ts.map +1 -0
  156. package/dist/syncer/syncer.js +2 -0
  157. package/dist/syncer/syncer.js.map +1 -0
  158. package/dist/templates/base-template.d.ts +13 -0
  159. package/dist/templates/base-template.d.ts.map +1 -0
  160. package/dist/templates/base-template.js +2 -0
  161. package/dist/templates/base-template.js.map +1 -0
  162. package/dist/templates/entity.template.d.ts +17 -0
  163. package/dist/templates/entity.template.d.ts.map +1 -0
  164. package/dist/templates/entity.template.js +2 -0
  165. package/dist/templates/entity.template.js.map +1 -0
  166. package/dist/templates/generated.template.d.ts +27 -0
  167. package/dist/templates/generated.template.d.ts.map +1 -0
  168. package/dist/templates/generated.template.js +2 -0
  169. package/dist/templates/generated.template.js.map +1 -0
  170. package/dist/templates/generated_http.template.d.ts +24 -0
  171. package/dist/templates/generated_http.template.d.ts.map +1 -0
  172. package/dist/templates/generated_http.template.js +2 -0
  173. package/dist/templates/generated_http.template.js.map +1 -0
  174. package/dist/templates/generated_sso.template.d.ts +20 -0
  175. package/dist/templates/generated_sso.template.d.ts.map +1 -0
  176. package/dist/templates/generated_sso.template.js +2 -0
  177. package/dist/templates/generated_sso.template.js.map +1 -0
  178. package/dist/templates/index.d.ts +2 -0
  179. package/dist/templates/index.d.ts.map +1 -0
  180. package/dist/templates/index.js +2 -0
  181. package/dist/templates/index.js.map +1 -0
  182. package/dist/templates/init_types.template.d.ts +17 -0
  183. package/dist/templates/init_types.template.d.ts.map +1 -0
  184. package/dist/templates/init_types.template.js +2 -0
  185. package/dist/templates/init_types.template.js.map +1 -0
  186. package/dist/templates/model.template.d.ts +17 -0
  187. package/dist/templates/model.template.d.ts.map +1 -0
  188. package/dist/templates/model.template.js +2 -0
  189. package/dist/templates/model.template.js.map +1 -0
  190. package/dist/templates/model_test.template.d.ts +17 -0
  191. package/dist/templates/model_test.template.d.ts.map +1 -0
  192. package/dist/templates/model_test.template.js +2 -0
  193. package/dist/templates/model_test.template.js.map +1 -0
  194. package/dist/templates/service.template.d.ts +29 -0
  195. package/dist/templates/service.template.d.ts.map +1 -0
  196. package/dist/templates/service.template.js +2 -0
  197. package/dist/templates/service.template.js.map +1 -0
  198. package/dist/templates/view_enums_buttonset.template.d.ts +17 -0
  199. package/dist/templates/view_enums_buttonset.template.d.ts.map +1 -0
  200. package/dist/templates/view_enums_buttonset.template.js +2 -0
  201. package/dist/templates/view_enums_buttonset.template.js.map +1 -0
  202. package/dist/templates/view_enums_dropdown.template.d.ts +18 -0
  203. package/dist/templates/view_enums_dropdown.template.d.ts.map +1 -0
  204. package/dist/templates/view_enums_dropdown.template.js +2 -0
  205. package/dist/templates/view_enums_dropdown.template.js.map +1 -0
  206. package/dist/templates/view_enums_select.template.d.ts +17 -0
  207. package/dist/templates/view_enums_select.template.d.ts.map +1 -0
  208. package/dist/templates/view_enums_select.template.js +2 -0
  209. package/dist/templates/view_enums_select.template.js.map +1 -0
  210. package/dist/templates/view_form.template.d.ts +26 -0
  211. package/dist/templates/view_form.template.d.ts.map +1 -0
  212. package/dist/templates/view_form.template.js +2 -0
  213. package/dist/templates/view_form.template.js.map +1 -0
  214. package/dist/templates/view_id_all_select.template.d.ts +17 -0
  215. package/dist/templates/view_id_all_select.template.d.ts.map +1 -0
  216. package/dist/templates/view_id_all_select.template.js +2 -0
  217. package/dist/templates/view_id_all_select.template.js.map +1 -0
  218. package/dist/templates/view_id_async_select.template.d.ts +17 -0
  219. package/dist/templates/view_id_async_select.template.d.ts.map +1 -0
  220. package/dist/templates/view_id_async_select.template.js +2 -0
  221. package/dist/templates/view_id_async_select.template.js.map +1 -0
  222. package/dist/templates/view_list.template.d.ts +38 -0
  223. package/dist/templates/view_list.template.d.ts.map +1 -0
  224. package/dist/templates/view_list.template.js +2 -0
  225. package/dist/templates/view_list.template.js.map +1 -0
  226. package/dist/templates/view_list_columns.template.d.ts +17 -0
  227. package/dist/templates/view_list_columns.template.d.ts.map +1 -0
  228. package/dist/templates/view_list_columns.template.js +2 -0
  229. package/dist/templates/view_list_columns.template.js.map +1 -0
  230. package/dist/templates/view_search_input.template.d.ts +17 -0
  231. package/dist/templates/view_search_input.template.d.ts.map +1 -0
  232. package/dist/templates/view_search_input.template.js +2 -0
  233. package/dist/templates/view_search_input.template.js.map +1 -0
  234. package/dist/testing/_relation-graph.d.ts +7 -0
  235. package/dist/testing/_relation-graph.d.ts.map +1 -0
  236. package/dist/testing/_relation-graph.js +2 -0
  237. package/dist/testing/_relation-graph.js.map +1 -0
  238. package/dist/testing/fixture-manager.d.ts +35 -0
  239. package/dist/testing/fixture-manager.d.ts.map +1 -0
  240. package/dist/testing/fixture-manager.js +2 -0
  241. package/dist/testing/fixture-manager.js.map +1 -0
  242. package/dist/types/types.d.ts +609 -0
  243. package/dist/types/types.d.ts.map +1 -0
  244. package/dist/types/types.js +2 -0
  245. package/dist/types/types.js.map +1 -0
  246. package/dist/typings/knex.d.js +2 -0
  247. package/dist/typings/knex.d.js.map +1 -0
  248. package/dist/utils/async-utils.d.ts +25 -0
  249. package/dist/utils/async-utils.d.ts.map +1 -0
  250. package/dist/utils/async-utils.js +2 -0
  251. package/dist/utils/async-utils.js.map +1 -0
  252. package/dist/utils/controller.d.ts +9 -0
  253. package/dist/utils/controller.d.ts.map +1 -0
  254. package/dist/utils/controller.js +2 -0
  255. package/dist/utils/controller.js.map +1 -0
  256. package/dist/utils/fs-utils.d.ts +9 -0
  257. package/dist/utils/fs-utils.d.ts.map +1 -0
  258. package/dist/utils/fs-utils.js +2 -0
  259. package/dist/utils/fs-utils.js.map +1 -0
  260. package/dist/utils/lodash-able.d.ts +2 -0
  261. package/dist/utils/lodash-able.d.ts.map +1 -0
  262. package/dist/utils/lodash-able.js +2 -0
  263. package/dist/utils/lodash-able.js.map +1 -0
  264. package/dist/utils/model.d.ts +17 -0
  265. package/dist/utils/model.d.ts.map +1 -0
  266. package/dist/utils/model.js +2 -0
  267. package/dist/utils/model.js.map +1 -0
  268. package/dist/utils/sql-parser.d.ts +4 -0
  269. package/dist/utils/sql-parser.d.ts.map +1 -0
  270. package/dist/utils/sql-parser.js +2 -0
  271. package/dist/utils/sql-parser.js.map +1 -0
  272. package/dist/utils/utils.d.ts +9 -0
  273. package/dist/utils/utils.d.ts.map +1 -0
  274. package/dist/utils/utils.js +2 -0
  275. package/dist/utils/utils.js.map +1 -0
  276. package/dist/utils/zod-error.d.ts +8 -0
  277. package/dist/utils/zod-error.d.ts.map +1 -0
  278. package/dist/utils/zod-error.js +2 -0
  279. package/dist/utils/zod-error.js.map +1 -0
  280. package/nodemon.json +6 -0
  281. package/package.json +29 -44
  282. package/src/api/base-frame.ts +3 -4
  283. package/src/api/caster.ts +22 -23
  284. package/src/api/code-converters.ts +170 -134
  285. package/src/api/context.ts +13 -6
  286. package/src/api/decorators.ts +146 -20
  287. package/src/api/index.ts +2 -0
  288. package/src/api/sonamu.ts +374 -165
  289. package/src/bin/build-config.ts +5 -0
  290. package/src/bin/cli-wrapper.ts +29 -40
  291. package/src/bin/cli.ts +132 -190
  292. package/src/database/_batch_update.ts +10 -15
  293. package/src/database/base-model.ts +300 -216
  294. package/src/database/db.ts +191 -21
  295. package/src/database/{drivers/knex/plugins → knex-plugins}/knex-on-duplicate-update.ts +1 -1
  296. package/src/database/puri-wrapper.ts +129 -0
  297. package/src/database/puri.ts +808 -0
  298. package/src/database/puri.types.ts +222 -0
  299. package/src/database/transaction-context.ts +18 -0
  300. package/src/database/upsert-builder.ts +32 -35
  301. package/src/entity/entity-manager.ts +7 -15
  302. package/src/entity/entity.ts +9 -31
  303. package/src/entity/migrator-/354/235/264/354/202/254/352/260/224/354/226/264/354/232/224.md +1 -0
  304. package/src/file-storage/driver.ts +121 -0
  305. package/src/file-storage/file-storage.ts +100 -0
  306. package/src/index.ts +14 -11
  307. package/src/migration/code-generation.ts +777 -0
  308. package/src/migration/migration-set.ts +453 -0
  309. package/src/migration/migrator.ts +823 -0
  310. package/src/migration/types.ts +53 -0
  311. package/src/shared/web.shared.ts.txt +33 -2
  312. package/src/syncer/syncer.ts +294 -127
  313. package/src/templates/generated.template.ts +13 -1
  314. package/src/templates/generated_http.template.ts +15 -12
  315. package/src/templates/generated_sso.template.ts +50 -2
  316. package/src/templates/model.template.ts +138 -2
  317. package/src/templates/service.template.ts +0 -1
  318. package/src/templates/view_form.template.ts +11 -7
  319. package/src/templates/view_list.template.ts +12 -4
  320. package/src/testing/fixture-manager.ts +229 -174
  321. package/src/types/types.ts +102 -14
  322. package/src/utils/async-utils.ts +64 -0
  323. package/src/utils/fs-utils.ts +17 -0
  324. package/src/utils/model.ts +0 -2
  325. package/src/utils/utils.ts +14 -58
  326. package/src/utils/zod-error.ts +12 -176
  327. package/tsconfig.json +2 -0
  328. package/tsup.config.js +4 -2
  329. package/.pnp.cjs +0 -14363
  330. package/.pnp.loader.mjs +0 -2047
  331. package/.vscode/extensions.json +0 -6
  332. package/.vscode/settings.json +0 -9
  333. package/.yarnrc.yml +0 -5
  334. package/src/database/base-model.abstract.ts +0 -97
  335. package/src/database/db.abstract.ts +0 -75
  336. package/src/database/drivers/knex/base-model.ts +0 -55
  337. package/src/database/drivers/knex/client.ts +0 -209
  338. package/src/database/drivers/knex/db.ts +0 -232
  339. package/src/database/drivers/knex/generator.ts +0 -659
  340. package/src/database/drivers/kysely/base-model.ts +0 -89
  341. package/src/database/drivers/kysely/client.ts +0 -309
  342. package/src/database/drivers/kysely/db.ts +0 -238
  343. package/src/database/drivers/kysely/generator.ts +0 -714
  344. package/src/database/types.ts +0 -118
  345. package/src/entity/migrator.ts +0 -1400
  346. package/src/smd/smd-manager.ts +0 -139
  347. package/src/smd/smd.ts +0 -571
  348. package/src/templates/kysely_types.template.ts +0 -205
@@ -1,89 +0,0 @@
1
- import { Kysely, SelectQueryBuilder } from "kysely";
2
- import { SubsetQuery, isCustomJoinClause } from "../../../types/types";
3
- import { BaseModelClassAbstract } from "../../base-model";
4
- import { DB } from "../../db";
5
- import { DBPreset, Database } from "../../types";
6
- import { KyselyClient } from "./client";
7
- import { UpsertBuilder } from "../../upsert-builder";
8
- import { UndirectedOrderByExpression } from "kysely/dist/cjs/parser/order-by-parser";
9
- import { EntityManager } from "../../../entity/entity-manager";
10
- import inflection from "inflection";
11
-
12
- type TB = keyof Database;
13
-
14
- export class BaseModelClass extends BaseModelClassAbstract<"kysely"> {
15
- getDB(which: DBPreset): Kysely<Database> {
16
- return DB.getDB(which) as Kysely<Database>;
17
- }
18
-
19
- async destroy(): Promise<void> {
20
- return DB.destroy();
21
- }
22
-
23
- getUpsertBuilder() {
24
- return new UpsertBuilder<"kysely">();
25
- }
26
-
27
- protected applyJoins(
28
- clonedQb: KyselyClient,
29
- joins: SubsetQuery["joins"]
30
- ): KyselyClient {
31
- for (const join of joins) {
32
- if (isCustomJoinClause(join)) {
33
- throw new Error("Custom join clause is not supported in Kysely");
34
- }
35
-
36
- if (join.join === "inner") {
37
- clonedQb.innerJoin(`${join.table} as ${join.as}`, join.from, join.to);
38
- } else if (join.join === "outer") {
39
- clonedQb.leftJoin(`${join.table} as ${join.as}`, join.from, join.to);
40
- }
41
- }
42
-
43
- return clonedQb;
44
- }
45
-
46
- protected async executeCountQuery(
47
- qb: SelectQueryBuilder<Database, TB, any>
48
- ): Promise<number> {
49
- const result = await qb
50
- .clearSelect()
51
- .select((eb) => eb.fn.count("id" as any).as("total"))
52
- .executeTakeFirstOrThrow();
53
- return Number(result.total);
54
- }
55
-
56
- parseOrderBy(
57
- orderBy: string
58
- ): [
59
- UndirectedOrderByExpression<Database, keyof Database, {}>,
60
- "asc" | "desc",
61
- ] {
62
- const [_column, order] = orderBy.split("-");
63
- // FIXME: 조인 2개 이상일 때 처리
64
- const [table, column] = _column.includes(".")
65
- ? _column.split(".")
66
- : [inflection.tableize(this.modelName), _column];
67
-
68
- if (order !== "asc" && order !== "desc") {
69
- throw new Error("parseOrderBy: Invalid order");
70
- }
71
- if (!column) {
72
- throw new Error("parseOrderBy: Invalid column");
73
- }
74
-
75
- const entity = EntityManager.get(inflection.classify(table));
76
- if (!entity.props.find((p) => p.name === column)) {
77
- throw new Error("parseOrderBy: 현재 엔티티에 존재하지 않는 컬럼입니다: ");
78
- }
79
-
80
- return [
81
- `${table}.${column}` as unknown as UndirectedOrderByExpression<
82
- Database,
83
- keyof Database,
84
- {}
85
- >,
86
- order as "asc" | "desc",
87
- ];
88
- }
89
- }
@@ -1,309 +0,0 @@
1
- import {
2
- ComparisonOperatorExpression,
3
- FileMigrationProvider,
4
- Kysely,
5
- Migrator,
6
- MysqlDialect,
7
- Transaction,
8
- sql,
9
- } from "kysely";
10
- import {
11
- Database,
12
- DatabaseClient,
13
- DriverSpec,
14
- KyselyConfig,
15
- WhereClause,
16
- } from "../../types";
17
- import _ from "lodash";
18
- import { asArray } from "../../../utils/model";
19
- import { createPool } from "mysql2";
20
-
21
- type TB = keyof Database;
22
- type TE = TB & string;
23
-
24
- // 확장된 Transaction 타입 정의
25
- export type ExtendedKyselyTrx = Transaction<Database> &
26
- DatabaseClient<"kysely">;
27
-
28
- export class KyselyClient implements DatabaseClient<"kysely"> {
29
- private kysely: Kysely<Database>;
30
-
31
- get connectionInfo() {
32
- return {
33
- host: this.config.host,
34
- port: this.config.port,
35
- database: this.config.database,
36
- user: this.config.user,
37
- password: this.config.password,
38
- };
39
- }
40
-
41
- private _qb?: DriverSpec["kysely"]["queryBuilder"];
42
- set qb(qb: DriverSpec["kysely"]["queryBuilder"]) {
43
- this._qb = qb;
44
- }
45
- get qb() {
46
- if (!this._qb) {
47
- throw new Error("QueryBuilder is not initialized");
48
- }
49
- return this._qb;
50
- }
51
-
52
- private _migrator?: Migrator;
53
- set migrator(migrator: Migrator) {
54
- this._migrator = migrator;
55
- }
56
- get migrator() {
57
- if (!this._migrator) {
58
- throw new Error("Migrator is not initialized");
59
- }
60
- return this._migrator;
61
- }
62
-
63
- get sql() {
64
- const bindings = this.qb.compile().parameters.map((p) => JSON.stringify(p));
65
- return this.qb.compile().sql.replace(/\?/g, () => bindings.shift()!);
66
- }
67
-
68
- constructor(
69
- private config: KyselyConfig,
70
- kysely?: Kysely<Database>
71
- ) {
72
- const { onCreateConnection, migration, ...rest } = this.config;
73
-
74
- this.kysely =
75
- kysely ??
76
- new Kysely({
77
- dialect: new MysqlDialect({
78
- onCreateConnection,
79
- pool: createPool(rest),
80
- }),
81
- });
82
-
83
- this.migrator = new Migrator({
84
- db: this.kysely,
85
- provider: new FileMigrationProvider(migration as any),
86
- });
87
- }
88
-
89
- from(table: string) {
90
- this.qb = this.kysely.selectFrom(table as TB);
91
- return this;
92
- }
93
-
94
- innerJoin(table: string, k1: string, k2: string) {
95
- this.qb = this.qb.innerJoin(table as TB, k1 as TB, k2 as TB);
96
- return this;
97
- }
98
-
99
- leftJoin(table: string, k1: string, k2: string) {
100
- this.qb = this.qb.leftJoin(table as TB, k1 as TB, k2 as TB);
101
- return this;
102
- }
103
-
104
- clearSelect() {
105
- this.qb = this.qb.clearSelect();
106
- return this;
107
- }
108
-
109
- select(columns: string | string[]) {
110
- this.qb = this.qb.select(asArray(columns) as TE[]);
111
- return this;
112
- }
113
-
114
- selectAll() {
115
- this.qb = this.qb.selectAll();
116
- return this;
117
- }
118
-
119
- where(ops: WhereClause | WhereClause[]) {
120
- if (typeof ops[0] === "string") {
121
- ops = [ops as WhereClause];
122
- }
123
- for (const [lhs, op, rhs] of asArray(ops)) {
124
- this.qb = this.qb.where(
125
- lhs as any,
126
- op as ComparisonOperatorExpression,
127
- rhs
128
- );
129
- }
130
- return this;
131
- }
132
-
133
- orWhere(ops: WhereClause | WhereClause[]) {
134
- this.qb = this.qb.where((eb) =>
135
- eb.or(
136
- ops.map(([lhs, op, rhs]) =>
137
- eb(lhs as any, op as ComparisonOperatorExpression, rhs)
138
- )
139
- )
140
- );
141
- return this;
142
- }
143
-
144
- async insert(table: string, data: any[]) {
145
- await this.kysely
146
- .insertInto(table as TB)
147
- .values(data)
148
- .execute();
149
- }
150
-
151
- async upsert(table: string, data: any[]) {
152
- const q = this.kysely
153
- .insertInto(table as TB)
154
- .values(data)
155
- .onDuplicateKeyUpdate(() => {
156
- const updates: Record<string, any> = {};
157
- // 첫 번째 레코드의 키들을 기준으로 업데이트 설정
158
- Object.keys(data[0]).forEach((key) => {
159
- updates[key] = sql`VALUES(${sql.raw(key)})`; // VALUES 구문 사용
160
- });
161
- return updates;
162
- });
163
- await q.execute();
164
- }
165
-
166
- limit(limit: number) {
167
- this.qb = this.qb.limit(limit);
168
- return this;
169
- }
170
-
171
- offset(offset: number) {
172
- this.qb = this.qb.offset(offset);
173
- return this;
174
- }
175
-
176
- count(column: string, alias?: string) {
177
- this.qb = this.qb.select((eb) =>
178
- eb.fn.count(column as any).as(alias ?? column)
179
- );
180
- return this;
181
- }
182
-
183
- distinct(column: string) {
184
- this.qb = this.qb.distinctOn(column as any);
185
- return this;
186
- }
187
-
188
- first() {
189
- this.qb = this.qb.limit(1);
190
- return this;
191
- }
192
-
193
- async execute(trx?: ExtendedKyselyTrx): Promise<any[]> {
194
- if (trx) {
195
- const { rows } = await trx.executeQuery(this.qb.compile());
196
- return rows as any[];
197
- }
198
- return this.qb.execute();
199
- }
200
-
201
- async pluck(column: string): Promise<any[]> {
202
- const result = await this.execute();
203
- return result.map((row) => row[column]);
204
- }
205
-
206
- createRawQuery(query: string, bindings?: any[]) {
207
- if (bindings?.length) {
208
- query = query.replace(
209
- /\?/g,
210
- () => sql.lit(bindings.shift()).compile(this.kysely).sql
211
- );
212
- }
213
- return sql.raw(query).compile(this.kysely).sql;
214
- }
215
-
216
- async raw<R>(query: string, bindings?: any[]): Promise<R[]> {
217
- if (bindings?.length) {
218
- query = query.replace(
219
- /\?/g,
220
- () => sql.lit(bindings.shift()).compile(this.kysely).sql
221
- );
222
- }
223
- const { rows } = await sql.raw(query).execute(this.kysely);
224
- return rows as R[];
225
- }
226
-
227
- async truncate(table: string) {
228
- await sql`truncate table ${sql.table(table)}`.execute(this.kysely);
229
- }
230
-
231
- trx<T>(callback: (trx: KyselyClient) => Promise<T>) {
232
- return this.kysely
233
- .transaction()
234
- .execute(async (trx) => callback(new KyselyClient(this.config, trx)));
235
- }
236
-
237
- destroy() {
238
- return this.kysely.destroy();
239
- }
240
-
241
- clearQueryParts(parts: ("order" | "offset" | "limit")[]) {
242
- for (const part of parts) {
243
- switch (part) {
244
- case "order":
245
- this.qb = this.qb.clearOrderBy();
246
- break;
247
- case "offset":
248
- this.qb = this.qb.clearOffset();
249
- break;
250
- case "limit":
251
- this.qb = this.qb.clearLimit();
252
- break;
253
- }
254
- }
255
- return this;
256
- }
257
-
258
- clone() {
259
- const client = new KyselyClient(this.config);
260
- client.qb = this.qb;
261
- return client;
262
- }
263
-
264
- // Migrator
265
-
266
- async getMigrations() {
267
- const result = await this.migrator.getMigrations();
268
- return result.filter((r) => !r.executedAt).map((r) => r.name);
269
- }
270
-
271
- async status() {
272
- const pendings = await this.getMigrations();
273
- return 0 - pendings.length;
274
- }
275
-
276
- async migrate() {
277
- const { results, error } = await this.migrator.migrateToLatest();
278
- if (error) {
279
- throw error;
280
- }
281
-
282
- return [0, results?.map((r) => r.migrationName)];
283
- }
284
-
285
- async rollback() {
286
- const { results, error } = await this.migrator.migrateDown();
287
- if (error) {
288
- throw error;
289
- }
290
-
291
- return [0, results?.map((r) => r.migrationName)];
292
- }
293
-
294
- async rollbackAll() {
295
- while (true) {
296
- const { error, results } = await this.migrator.migrateDown();
297
-
298
- if (error) {
299
- console.error("Error while rollbackAll:", error);
300
- throw error;
301
- }
302
-
303
- if (!results || results.length === 0) {
304
- console.log("RollbackAll completed");
305
- break;
306
- }
307
- }
308
- }
309
- }
@@ -1,238 +0,0 @@
1
- import _ from "lodash";
2
- import { promises } from "fs";
3
- import path from "path";
4
- import { createPool } from "mysql2";
5
- import {
6
- DBPreset,
7
- Database,
8
- KyselyBaseConfig,
9
- KyselyConfig,
10
- SonamuKyselyDBConfig,
11
- } from "../../types";
12
- import { FileMigrationProviderProps, Kysely, MysqlDialect, sql } from "kysely";
13
- import { KyselyClient } from "./client";
14
- import { DBClass } from "../../db.abstract";
15
- import { Sonamu } from "../../../api";
16
- import { KyselyGenerator } from "./generator";
17
-
18
- export class DBKyselyClass extends DBClass {
19
- public migrationTable = "kysely_migration";
20
- public generator: KyselyGenerator = new KyselyGenerator();
21
- public baseConfig?: KyselyBaseConfig;
22
-
23
- public declare _fullConfig?: SonamuKyselyDBConfig;
24
- set fullConfig(config: SonamuKyselyDBConfig) {
25
- this._fullConfig = config;
26
- }
27
- get fullConfig() {
28
- if (!this._fullConfig) {
29
- throw new Error("DB Config has not been initialized");
30
- }
31
- return this._fullConfig;
32
- }
33
-
34
- private wdb?: Kysely<Database>;
35
- private rdb?: Kysely<Database>;
36
-
37
- private _tdb: KyselyClient | null = null;
38
- set tdb(tdb: KyselyClient) {
39
- this._tdb = tdb;
40
- }
41
- get tdb(): KyselyClient {
42
- if (this._tdb === null) {
43
- throw new Error("tdb has not been initialized");
44
- }
45
- return this._tdb;
46
- }
47
-
48
- private _fdb: KyselyClient | null = null;
49
- set fdb(fdb: KyselyClient) {
50
- this._fdb = fdb;
51
- }
52
- get fdb(): KyselyClient {
53
- if (this._fdb === null) {
54
- throw new Error("fdb has not been initialized");
55
- }
56
- return this._fdb;
57
- }
58
-
59
- get connectionInfo() {
60
- return _.mapValues(this.fullConfig, (config) => ({
61
- host: config.host ?? "localhost",
62
- port: config.port ?? 3306,
63
- database: config.database,
64
- user: config.user,
65
- password: config.password,
66
- }));
67
- }
68
-
69
- constructor() {
70
- super();
71
- }
72
-
73
- init(config: KyselyBaseConfig) {
74
- this.baseConfig = config;
75
- this.fullConfig = this.generateDBConfig(config);
76
- }
77
-
78
- async testInit() {
79
- if (this._tdb !== null) {
80
- return;
81
- }
82
-
83
- if (this.fullConfig.test && this.fullConfig.production_master) {
84
- const tConnInfo = this.fullConfig.test;
85
- const pConnInfo = this.fullConfig.production_master;
86
-
87
- if (
88
- `${tConnInfo.host ?? "localhost"}:${tConnInfo.port ?? 3306}/${
89
- tConnInfo.database
90
- }` ===
91
- `${pConnInfo.host ?? "localhost"}:${pConnInfo.port ?? 3306}/${pConnInfo.database}`
92
- ) {
93
- throw new Error(
94
- `테스트DB와 프로덕션DB에 동일한 데이터베이스가 사용되었습니다.`
95
- );
96
- }
97
- }
98
-
99
- this.tdb = new KyselyClient(this.fullConfig.test);
100
- this.fdb = new KyselyClient(this.fullConfig.fixture_local);
101
- }
102
-
103
- get config(): SonamuKyselyDBConfig {
104
- return this.fullConfig;
105
- }
106
-
107
- getDB(which: DBPreset) {
108
- const instanceName = which === "w" ? "wdb" : "rdb";
109
-
110
- if (!this[instanceName]) {
111
- const _config: KyselyConfig = this.getCurrentConfig(which);
112
- const { onCreateConnection, migration, ...config } = _config;
113
-
114
- this[instanceName] = new Kysely<Database>({
115
- dialect: new MysqlDialect({
116
- onCreateConnection,
117
- pool: createPool(config),
118
- }),
119
- });
120
- }
121
-
122
- return this[instanceName]!;
123
- }
124
-
125
- getClient(mode: keyof SonamuKyselyDBConfig) {
126
- return new KyselyClient(this.fullConfig[mode]);
127
- }
128
-
129
- async destroy(): Promise<void> {
130
- if (this.wdb !== undefined) {
131
- await this.wdb.destroy();
132
- this.wdb = undefined;
133
- }
134
- if (this.rdb !== undefined) {
135
- await this.rdb.destroy();
136
- this.rdb = undefined;
137
- }
138
- }
139
-
140
- async testDestroy() {
141
- if (this._tdb) {
142
- await this._tdb.destroy();
143
- this._tdb = null;
144
- }
145
- if (this._fdb) {
146
- await this._fdb.destroy();
147
- this._fdb = null;
148
- }
149
- }
150
-
151
- raw(db: Kysely<Database>, query: string) {
152
- return sql`${query}`.execute(db);
153
- }
154
-
155
- public generateDBConfig(config: KyselyBaseConfig): SonamuKyselyDBConfig {
156
- const defaultKyselyConfig = _.merge(
157
- {
158
- migration: {
159
- fs: promises,
160
- path,
161
- migrationFolder: path.join(Sonamu.apiRootPath, "/dist/migrations"),
162
- } as FileMigrationProviderProps,
163
- port: 3306,
164
- host: "localhost",
165
- database: config.database,
166
- },
167
- config.defaultOptions
168
- );
169
-
170
- // 로컬 환경 설정
171
- const test = _.merge({}, defaultKyselyConfig, {
172
- database: `${config.database}_test`,
173
- });
174
-
175
- const fixture_local = _.merge({}, defaultKyselyConfig, {
176
- database: `${config.database}_fixture`,
177
- });
178
-
179
- // 개발 환경 설정
180
- const devMasterOptions = config.environments?.development;
181
- const devSlaveOptions = config.environments?.development_slave;
182
- const development_master = _.merge(
183
- {},
184
- defaultKyselyConfig,
185
- devMasterOptions
186
- );
187
- const development_slave = _.merge(
188
- {},
189
- defaultKyselyConfig,
190
- devMasterOptions,
191
- devSlaveOptions
192
- );
193
- const fixture_remote = _.merge({}, defaultKyselyConfig, devMasterOptions, {
194
- database: `${config.database}_fixture`,
195
- });
196
-
197
- // 프로덕션 환경 설정
198
- const prodMasterOptions = config.environments?.production ?? {};
199
- const prodSlaveOptions = config.environments?.production_slave ?? {};
200
- const production_master = _.merge(
201
- {},
202
- defaultKyselyConfig,
203
- prodMasterOptions
204
- );
205
- const production_slave = _.merge(
206
- {},
207
- defaultKyselyConfig,
208
- prodMasterOptions,
209
- prodSlaveOptions
210
- );
211
-
212
- return {
213
- test,
214
- fixture_local,
215
- fixture_remote,
216
- development_master,
217
- development_slave,
218
- production_master,
219
- production_slave,
220
- };
221
- }
222
-
223
- /**
224
- * keys에 해당하는 설정들을 중복없이 가져옵니다. (host/port/database가 같은 설정은 중복으로 처리합니다.)
225
- */
226
- getUniqueConfigs(keys: (keyof SonamuKyselyDBConfig)[]) {
227
- const targets = keys.map((key) => ({
228
- connKey: key,
229
- options: this.fullConfig[key as keyof SonamuKyselyDBConfig],
230
- }));
231
-
232
- return _.uniqBy(
233
- targets,
234
- ({ options }) =>
235
- `${options.host ?? "localhost"}:${options.port ?? 3306}/${options.database}`
236
- );
237
- }
238
- }