sonamu 0.5.6 → 0.6.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 (365) hide show
  1. package/dist/api/base-frame.js +12 -2
  2. package/dist/api/caster.js +66 -2
  3. package/dist/api/code-converters.js +489 -2
  4. package/dist/api/config.d.ts +76 -0
  5. package/dist/api/config.d.ts.map +1 -0
  6. package/dist/api/config.js +32 -0
  7. package/dist/api/context.d.ts +1 -0
  8. package/dist/api/context.d.ts.map +1 -1
  9. package/dist/api/context.js +3 -2
  10. package/dist/api/decorators.d.ts +1 -0
  11. package/dist/api/decorators.d.ts.map +1 -1
  12. package/dist/api/decorators.js +142 -2
  13. package/dist/api/index.js +9 -2
  14. package/dist/api/sonamu.d.ts +8 -22
  15. package/dist/api/sonamu.d.ts.map +1 -1
  16. package/dist/api/sonamu.js +482 -2
  17. package/dist/bin/build-config.d.ts +2 -1
  18. package/dist/bin/build-config.d.ts.map +1 -1
  19. package/dist/bin/build-config.js +12 -2
  20. package/dist/bin/cli-wrapper.js +71 -2
  21. package/dist/bin/cli.js +418 -2
  22. package/dist/bin/hot-hook-register.d.ts +11 -0
  23. package/dist/bin/hot-hook-register.d.ts.map +1 -0
  24. package/dist/bin/hot-hook-register.js +21 -0
  25. package/dist/database/_batch_update.js +78 -2
  26. package/dist/database/base-model.js +247 -2
  27. package/dist/database/code-generator.js +53 -2
  28. package/dist/database/db.d.ts +5 -16
  29. package/dist/database/db.d.ts.map +1 -1
  30. package/dist/database/db.js +132 -2
  31. package/dist/database/knex-plugins/knex-on-duplicate-update.js +39 -2
  32. package/dist/database/puri-wrapper.d.ts +22 -10
  33. package/dist/database/puri-wrapper.d.ts.map +1 -1
  34. package/dist/database/puri-wrapper.js +109 -2
  35. package/dist/database/puri.d.ts +105 -73
  36. package/dist/database/puri.d.ts.map +1 -1
  37. package/dist/database/puri.js +539 -2
  38. package/dist/database/puri.types.d.ts +33 -42
  39. package/dist/database/puri.types.d.ts.map +1 -1
  40. package/dist/database/puri.types.js +3 -2
  41. package/dist/database/transaction-context.d.ts +3 -3
  42. package/dist/database/transaction-context.d.ts.map +1 -1
  43. package/dist/database/transaction-context.js +14 -2
  44. package/dist/database/upsert-builder.js +215 -2
  45. package/dist/entity/entity-manager.d.ts +3 -1
  46. package/dist/entity/entity-manager.d.ts.map +1 -1
  47. package/dist/entity/entity-manager.js +114 -2
  48. package/dist/entity/entity-utils.js +210 -2
  49. package/dist/entity/entity.d.ts.map +1 -1
  50. package/dist/entity/entity.js +651 -2
  51. package/dist/exceptions/error-handler.js +29 -2
  52. package/dist/exceptions/so-exceptions.js +85 -2
  53. package/dist/file-storage/driver.js +79 -2
  54. package/dist/file-storage/file-storage.js +75 -2
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +28 -2
  58. package/dist/migration/code-generation.js +558 -2
  59. package/dist/migration/migration-set.js +364 -2
  60. package/dist/migration/migrator.d.ts +0 -9
  61. package/dist/migration/migrator.d.ts.map +1 -1
  62. package/dist/migration/migrator.js +510 -2
  63. package/dist/migration/types.js +3 -2
  64. package/dist/naite/naite.d.ts +12 -0
  65. package/dist/naite/naite.d.ts.map +1 -0
  66. package/dist/naite/naite.js +72 -0
  67. package/dist/stream/index.js +3 -2
  68. package/dist/stream/sse.js +38 -2
  69. package/dist/syncer/api-parser.d.ts +20 -0
  70. package/dist/syncer/api-parser.d.ts.map +1 -0
  71. package/dist/syncer/api-parser.js +229 -0
  72. package/dist/syncer/checksum.d.ts +21 -0
  73. package/dist/syncer/checksum.d.ts.map +1 -0
  74. package/dist/syncer/checksum.js +98 -0
  75. package/dist/syncer/code-generator.d.ts +20 -0
  76. package/dist/syncer/code-generator.d.ts.map +1 -0
  77. package/dist/syncer/code-generator.js +141 -0
  78. package/dist/syncer/entity-operations.d.ts +17 -0
  79. package/dist/syncer/entity-operations.d.ts.map +1 -0
  80. package/dist/syncer/entity-operations.js +58 -0
  81. package/dist/syncer/file-patterns.d.ts +29 -0
  82. package/dist/syncer/file-patterns.d.ts.map +1 -0
  83. package/dist/syncer/file-patterns.js +38 -0
  84. package/dist/syncer/index.d.ts +6 -0
  85. package/dist/syncer/index.d.ts.map +1 -1
  86. package/dist/syncer/index.js +9 -2
  87. package/dist/syncer/module-loader.d.ts +35 -0
  88. package/dist/syncer/module-loader.d.ts.map +1 -0
  89. package/dist/syncer/module-loader.js +82 -0
  90. package/dist/syncer/syncer.d.ts +93 -108
  91. package/dist/syncer/syncer.d.ts.map +1 -1
  92. package/dist/syncer/syncer.js +375 -2
  93. package/dist/template/entity-converter.d.ts +14 -0
  94. package/dist/template/entity-converter.d.ts.map +1 -0
  95. package/dist/template/entity-converter.js +101 -0
  96. package/dist/template/helpers.d.ts +23 -0
  97. package/dist/template/helpers.d.ts.map +1 -0
  98. package/dist/template/helpers.js +64 -0
  99. package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
  100. package/dist/template/implementations/entity.template.d.ts.map +1 -0
  101. package/dist/template/implementations/entity.template.js +87 -0
  102. package/dist/{templates → template/implementations}/generated.template.d.ts +3 -3
  103. package/dist/template/implementations/generated.template.d.ts.map +1 -0
  104. package/dist/template/implementations/generated.template.js +232 -0
  105. package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -3
  106. package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
  107. package/dist/template/implementations/generated_http.template.js +131 -0
  108. package/dist/{templates → template/implementations}/generated_sso.template.d.ts +3 -3
  109. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
  110. package/dist/template/implementations/generated_sso.template.js +105 -0
  111. package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
  112. package/dist/template/implementations/init_types.template.d.ts.map +1 -0
  113. package/dist/template/implementations/init_types.template.js +38 -0
  114. package/dist/template/implementations/model.template.d.ts +17 -0
  115. package/dist/template/implementations/model.template.d.ts.map +1 -0
  116. package/dist/template/implementations/model.template.js +171 -0
  117. package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
  118. package/dist/template/implementations/model_test.template.d.ts.map +1 -0
  119. package/dist/template/implementations/model_test.template.js +35 -0
  120. package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
  121. package/dist/template/implementations/service.template.d.ts.map +1 -0
  122. package/dist/template/implementations/service.template.js +193 -0
  123. package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
  124. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
  125. package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
  126. package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
  127. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
  128. package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
  129. package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
  130. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
  131. package/dist/template/implementations/view_enums_select.template.js +55 -0
  132. package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
  133. package/dist/template/implementations/view_form.template.d.ts.map +1 -0
  134. package/dist/template/implementations/view_form.template.js +337 -0
  135. package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
  136. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
  137. package/dist/template/implementations/view_id_all_select.template.js +31 -0
  138. package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
  139. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
  140. package/dist/template/implementations/view_id_async_select.template.js +105 -0
  141. package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
  142. package/dist/template/implementations/view_list.template.d.ts.map +1 -0
  143. package/dist/template/implementations/view_list.template.js +465 -0
  144. package/dist/{templates → template/implementations}/view_list_columns.template.d.ts +3 -3
  145. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
  146. package/dist/template/implementations/view_list_columns.template.js +49 -0
  147. package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
  148. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
  149. package/dist/template/implementations/view_search_input.template.js +64 -0
  150. package/dist/template/index.d.ts +5 -0
  151. package/dist/template/index.d.ts.map +1 -0
  152. package/dist/template/index.js +6 -0
  153. package/dist/template/template.d.ts +39 -0
  154. package/dist/template/template.d.ts.map +1 -0
  155. package/dist/template/template.js +47 -0
  156. package/dist/template/zod-converter.d.ts +18 -0
  157. package/dist/template/zod-converter.d.ts.map +1 -0
  158. package/dist/template/zod-converter.js +166 -0
  159. package/dist/testing/_relation-graph.js +80 -2
  160. package/dist/testing/fixture-manager.d.ts.map +1 -1
  161. package/dist/testing/fixture-manager.js +521 -2
  162. package/dist/types/types.d.ts +39 -40
  163. package/dist/types/types.d.ts.map +1 -1
  164. package/dist/types/types.js +289 -2
  165. package/dist/typings/knex.d.js +3 -2
  166. package/dist/utils/async-utils.d.ts +7 -0
  167. package/dist/utils/async-utils.d.ts.map +1 -1
  168. package/dist/utils/async-utils.js +57 -2
  169. package/dist/utils/console-util.d.ts +2 -0
  170. package/dist/utils/console-util.d.ts.map +1 -0
  171. package/dist/utils/console-util.js +6 -0
  172. package/dist/utils/controller.js +26 -2
  173. package/dist/utils/esm-utils.d.ts +45 -0
  174. package/dist/utils/esm-utils.d.ts.map +1 -0
  175. package/dist/utils/esm-utils.js +56 -0
  176. package/dist/utils/fs-utils.js +17 -2
  177. package/dist/utils/lodash-able.js +6 -2
  178. package/dist/utils/model.js +22 -2
  179. package/dist/utils/path-utils.d.ts +89 -0
  180. package/dist/utils/path-utils.d.ts.map +1 -0
  181. package/dist/utils/path-utils.js +60 -0
  182. package/dist/utils/process-utils.d.ts +13 -0
  183. package/dist/utils/process-utils.d.ts.map +1 -0
  184. package/dist/utils/process-utils.js +36 -0
  185. package/dist/utils/sql-parser.js +35 -2
  186. package/dist/utils/utils.d.ts +4 -7
  187. package/dist/utils/utils.d.ts.map +1 -1
  188. package/dist/utils/utils.js +33 -2
  189. package/dist/utils/zod-error.d.ts.map +1 -1
  190. package/dist/utils/zod-error.js +19 -2
  191. package/package.json +21 -9
  192. package/src/api/code-converters.ts +2 -2
  193. package/src/api/config.ts +142 -0
  194. package/src/api/context.ts +1 -0
  195. package/src/api/decorators.ts +15 -5
  196. package/src/api/sonamu.ts +102 -87
  197. package/src/bin/build-config.ts +2 -1
  198. package/src/bin/cli-wrapper.ts +10 -3
  199. package/src/bin/cli.ts +108 -56
  200. package/src/bin/hot-hook-register.ts +22 -0
  201. package/src/database/base-model.ts +1 -1
  202. package/src/database/code-generator.ts +1 -1
  203. package/src/database/db.ts +53 -60
  204. package/src/database/puri-wrapper.ts +104 -26
  205. package/src/database/puri.ts +477 -580
  206. package/src/database/puri.types.ts +111 -201
  207. package/src/database/transaction-context.ts +4 -4
  208. package/src/database/upsert-builder.ts +1 -1
  209. package/src/entity/entity-manager.ts +19 -15
  210. package/src/entity/entity.ts +4 -3
  211. package/src/index.ts +2 -0
  212. package/src/migration/code-generation.ts +1 -1
  213. package/src/migration/migration-set.ts +1 -1
  214. package/src/migration/migrator.ts +23 -152
  215. package/src/naite/naite.ts +70 -0
  216. package/src/syncer/api-parser.ts +299 -0
  217. package/src/syncer/checksum.ts +152 -0
  218. package/src/syncer/code-generator.ts +202 -0
  219. package/src/syncer/entity-operations.ts +68 -0
  220. package/src/syncer/file-patterns.ts +56 -0
  221. package/src/syncer/index.ts +6 -0
  222. package/src/syncer/module-loader.ts +125 -0
  223. package/src/syncer/syncer.ts +363 -1420
  224. package/src/template/entity-converter.ts +123 -0
  225. package/src/template/helpers.ts +84 -0
  226. package/src/{templates → template/implementations}/entity.template.ts +4 -4
  227. package/src/{templates → template/implementations}/generated.template.ts +9 -9
  228. package/src/{templates → template/implementations}/generated_http.template.ts +9 -6
  229. package/src/{templates → template/implementations}/generated_sso.template.ts +7 -7
  230. package/src/{templates → template/implementations}/init_types.template.ts +4 -4
  231. package/src/{templates → template/implementations}/model.template.ts +9 -9
  232. package/src/{templates → template/implementations}/model_test.template.ts +5 -5
  233. package/src/{templates → template/implementations}/service.template.ts +29 -12
  234. package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
  235. package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +5 -21
  236. package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
  237. package/src/{templates → template/implementations}/view_form.template.ts +11 -13
  238. package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
  239. package/src/{templates → template/implementations}/view_id_async_select.template.ts +3 -3
  240. package/src/{templates → template/implementations}/view_list.template.ts +13 -64
  241. package/src/{templates → template/implementations}/view_list_columns.template.ts +3 -3
  242. package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
  243. package/src/template/index.ts +4 -0
  244. package/src/template/template.ts +86 -0
  245. package/src/template/zod-converter.ts +219 -0
  246. package/src/testing/fixture-manager.ts +8 -1
  247. package/src/types/types.ts +39 -62
  248. package/src/utils/async-utils.ts +17 -0
  249. package/src/utils/console-util.ts +4 -0
  250. package/src/utils/esm-utils.ts +69 -0
  251. package/src/utils/path-utils.ts +102 -0
  252. package/src/utils/process-utils.ts +46 -0
  253. package/src/utils/sql-parser.ts +1 -1
  254. package/src/utils/utils.ts +14 -40
  255. package/src/utils/zod-error.ts +0 -1
  256. package/dist/api/base-frame.js.map +0 -1
  257. package/dist/api/caster.js.map +0 -1
  258. package/dist/api/code-converters.js.map +0 -1
  259. package/dist/api/context.js.map +0 -1
  260. package/dist/api/decorators.js.map +0 -1
  261. package/dist/api/index.js.map +0 -1
  262. package/dist/api/sonamu.js.map +0 -1
  263. package/dist/bin/build-config.js.map +0 -1
  264. package/dist/bin/cli-wrapper.js.map +0 -1
  265. package/dist/bin/cli.js.map +0 -1
  266. package/dist/database/_batch_update.js.map +0 -1
  267. package/dist/database/base-model.js.map +0 -1
  268. package/dist/database/code-generator.js.map +0 -1
  269. package/dist/database/db.js.map +0 -1
  270. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
  271. package/dist/database/puri-wrapper.js.map +0 -1
  272. package/dist/database/puri.js.map +0 -1
  273. package/dist/database/puri.types.js.map +0 -1
  274. package/dist/database/transaction-context.js.map +0 -1
  275. package/dist/database/upsert-builder.js.map +0 -1
  276. package/dist/entity/entity-manager.js.map +0 -1
  277. package/dist/entity/entity-utils.js.map +0 -1
  278. package/dist/entity/entity.js.map +0 -1
  279. package/dist/exceptions/error-handler.js.map +0 -1
  280. package/dist/exceptions/so-exceptions.js.map +0 -1
  281. package/dist/file-storage/driver.js.map +0 -1
  282. package/dist/file-storage/file-storage.js.map +0 -1
  283. package/dist/index.js.map +0 -1
  284. package/dist/migration/code-generation.js.map +0 -1
  285. package/dist/migration/migration-set.js.map +0 -1
  286. package/dist/migration/migrator.js.map +0 -1
  287. package/dist/migration/types.js.map +0 -1
  288. package/dist/stream/index.js.map +0 -1
  289. package/dist/stream/sse.js.map +0 -1
  290. package/dist/syncer/index.js.map +0 -1
  291. package/dist/syncer/syncer.js.map +0 -1
  292. package/dist/templates/base-template.d.ts +0 -13
  293. package/dist/templates/base-template.d.ts.map +0 -1
  294. package/dist/templates/base-template.js +0 -2
  295. package/dist/templates/base-template.js.map +0 -1
  296. package/dist/templates/entity.template.d.ts.map +0 -1
  297. package/dist/templates/entity.template.js +0 -2
  298. package/dist/templates/entity.template.js.map +0 -1
  299. package/dist/templates/generated.template.d.ts.map +0 -1
  300. package/dist/templates/generated.template.js +0 -2
  301. package/dist/templates/generated.template.js.map +0 -1
  302. package/dist/templates/generated_http.template.d.ts.map +0 -1
  303. package/dist/templates/generated_http.template.js +0 -2
  304. package/dist/templates/generated_http.template.js.map +0 -1
  305. package/dist/templates/generated_sso.template.d.ts.map +0 -1
  306. package/dist/templates/generated_sso.template.js +0 -2
  307. package/dist/templates/generated_sso.template.js.map +0 -1
  308. package/dist/templates/index.d.ts +0 -2
  309. package/dist/templates/index.d.ts.map +0 -1
  310. package/dist/templates/index.js +0 -2
  311. package/dist/templates/index.js.map +0 -1
  312. package/dist/templates/init_types.template.d.ts.map +0 -1
  313. package/dist/templates/init_types.template.js +0 -2
  314. package/dist/templates/init_types.template.js.map +0 -1
  315. package/dist/templates/model.template.d.ts +0 -17
  316. package/dist/templates/model.template.d.ts.map +0 -1
  317. package/dist/templates/model.template.js +0 -2
  318. package/dist/templates/model.template.js.map +0 -1
  319. package/dist/templates/model_test.template.d.ts.map +0 -1
  320. package/dist/templates/model_test.template.js +0 -2
  321. package/dist/templates/model_test.template.js.map +0 -1
  322. package/dist/templates/service.template.d.ts.map +0 -1
  323. package/dist/templates/service.template.js +0 -2
  324. package/dist/templates/service.template.js.map +0 -1
  325. package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
  326. package/dist/templates/view_enums_buttonset.template.js +0 -2
  327. package/dist/templates/view_enums_buttonset.template.js.map +0 -1
  328. package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
  329. package/dist/templates/view_enums_dropdown.template.js +0 -2
  330. package/dist/templates/view_enums_dropdown.template.js.map +0 -1
  331. package/dist/templates/view_enums_select.template.d.ts.map +0 -1
  332. package/dist/templates/view_enums_select.template.js +0 -2
  333. package/dist/templates/view_enums_select.template.js.map +0 -1
  334. package/dist/templates/view_form.template.d.ts.map +0 -1
  335. package/dist/templates/view_form.template.js +0 -2
  336. package/dist/templates/view_form.template.js.map +0 -1
  337. package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
  338. package/dist/templates/view_id_all_select.template.js +0 -2
  339. package/dist/templates/view_id_all_select.template.js.map +0 -1
  340. package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
  341. package/dist/templates/view_id_async_select.template.js +0 -2
  342. package/dist/templates/view_id_async_select.template.js.map +0 -1
  343. package/dist/templates/view_list.template.d.ts.map +0 -1
  344. package/dist/templates/view_list.template.js +0 -2
  345. package/dist/templates/view_list.template.js.map +0 -1
  346. package/dist/templates/view_list_columns.template.d.ts.map +0 -1
  347. package/dist/templates/view_list_columns.template.js +0 -2
  348. package/dist/templates/view_list_columns.template.js.map +0 -1
  349. package/dist/templates/view_search_input.template.d.ts.map +0 -1
  350. package/dist/templates/view_search_input.template.js +0 -2
  351. package/dist/templates/view_search_input.template.js.map +0 -1
  352. package/dist/testing/_relation-graph.js.map +0 -1
  353. package/dist/testing/fixture-manager.js.map +0 -1
  354. package/dist/types/types.js.map +0 -1
  355. package/dist/typings/knex.d.js.map +0 -1
  356. package/dist/utils/async-utils.js.map +0 -1
  357. package/dist/utils/controller.js.map +0 -1
  358. package/dist/utils/fs-utils.js.map +0 -1
  359. package/dist/utils/lodash-able.js.map +0 -1
  360. package/dist/utils/model.js.map +0 -1
  361. package/dist/utils/sql-parser.js.map +0 -1
  362. package/dist/utils/utils.js.map +0 -1
  363. package/dist/utils/zod-error.js.map +0 -1
  364. package/src/templates/base-template.ts +0 -19
  365. package/src/templates/index.ts +0 -1
@@ -1,4 +1,4 @@
1
- import _ from "lodash";
1
+ import * as _ from "lodash-es";
2
2
  import equal from "fast-deep-equal";
3
3
  import { MigrationColumn, MigrationIndex } from "../types/types";
4
4
 
@@ -1,32 +1,10 @@
1
1
  export type DBPreset = "w" | "r";
2
2
  import knex, { Knex } from "knex";
3
- import path from "path";
4
- import _ from "lodash";
3
+ import * as _ from "lodash-es";
5
4
  import { Sonamu } from "../api";
6
- import { ServiceUnavailableException } from "../exceptions/so-exceptions";
7
5
  import { AsyncLocalStorage } from "async_hooks";
8
6
  import { TransactionContext } from "./transaction-context";
9
-
10
- type MySQLConfig = Omit<Knex.Config, "connection"> & {
11
- connection?: Knex.MySql2ConnectionConfig;
12
- };
13
-
14
- export type SonamuDBBaseConfig = {
15
- // 기본 데이터베이스 이름
16
- database: string;
17
-
18
- // 모든 환경에 적용될 기본 Knex 옵션
19
- defaultOptions?: MySQLConfig;
20
-
21
- // 환경별 설정
22
- environments?: {
23
- development?: MySQLConfig;
24
- development_slave?: MySQLConfig;
25
- production?: MySQLConfig;
26
- production_slave?: MySQLConfig;
27
- remote_fixture?: MySQLConfig;
28
- };
29
- };
7
+ import { DatabaseConfig, SonamuConfig } from "../api/config";
30
8
 
31
9
  export type SonamuDBConfig = {
32
10
  development_master: Knex.Config;
@@ -52,28 +30,28 @@ class DBClass {
52
30
  return this.transactionStorage.getStore() ?? new TransactionContext();
53
31
  }
54
32
 
55
- async readKnexfile(): Promise<SonamuDBConfig> {
56
- const dbConfigPath: string = path.join(
57
- Sonamu.apiRootPath,
58
- "/dist/configs/db.js"
59
- );
60
- try {
61
- const knexfileModule = await import(dbConfigPath);
62
- const config =
63
- knexfileModule.default?.default ??
64
- knexfileModule.default ??
65
- knexfileModule;
66
- return this.generateDBConfig(config);
67
- } catch {}
68
-
69
- throw new ServiceUnavailableException(
70
- `다음 경로에서 DB설정 파일을 찾을 수 없습니다: ${dbConfigPath}. 먼저 빌드(yarn build)를 수행해주세요.`
71
- );
72
- }
73
-
74
33
  getDB(which: DBPreset): Knex {
75
34
  const dbConfig = Sonamu.dbConfig;
76
35
 
36
+ // 테스트 트랜잭션 격리
37
+ if (process.env.NODE_ENV === "test") {
38
+ if (this.testTransaction) {
39
+ return this.testTransaction;
40
+ } else if (this.wdb) {
41
+ return this.wdb;
42
+ } else {
43
+ this["wdb"] = knex({
44
+ ...dbConfig["test"],
45
+ // 단일 풀
46
+ pool: {
47
+ min: 1,
48
+ max: 1,
49
+ },
50
+ });
51
+ return this["wdb"];
52
+ }
53
+ }
54
+
77
55
  const instanceName = which === "w" ? "wdb" : "rdb";
78
56
 
79
57
  if (!this[instanceName]) {
@@ -84,16 +62,14 @@ class DBClass {
84
62
  config =
85
63
  which === "w"
86
64
  ? dbConfig["development_master"]
87
- : dbConfig["development_slave"] ?? dbConfig["development_master"];
65
+ : (dbConfig["development_slave"] ??
66
+ dbConfig["development_master"]);
88
67
  break;
89
68
  case "production":
90
69
  config =
91
70
  which === "w"
92
71
  ? dbConfig["production_master"]
93
- : dbConfig["production_slave"] ?? dbConfig["production_master"];
94
- break;
95
- case "test":
96
- config = dbConfig["test"];
72
+ : (dbConfig["production_slave"] ?? dbConfig["production_master"]);
97
73
  break;
98
74
  default:
99
75
  throw new Error(
@@ -117,8 +93,8 @@ class DBClass {
117
93
  }
118
94
  }
119
95
 
120
- private generateDBConfig(config: SonamuDBBaseConfig): SonamuDBConfig {
121
- const defaultKnexConfig: Partial<MySQLConfig> = _.merge(
96
+ public generateDBConfig(config: SonamuConfig["database"]): SonamuDBConfig {
97
+ const defaultKnexConfig: Partial<DatabaseConfig> = _.merge(
122
98
  {
123
99
  client: "mysql2",
124
100
  pool: {
@@ -126,11 +102,10 @@ class DBClass {
126
102
  max: 5,
127
103
  },
128
104
  migrations: {
129
- extension: "js",
130
- directory: "./dist/migrations",
105
+ directory: "./src/migrations",
131
106
  },
132
107
  connection: {
133
- database: config.database,
108
+ database: config.name,
134
109
  ...config.defaultOptions?.connection,
135
110
  },
136
111
  },
@@ -138,16 +113,16 @@ class DBClass {
138
113
  );
139
114
 
140
115
  // 로컬 환경 설정
141
- const test: MySQLConfig = _.merge({}, defaultKnexConfig, {
116
+ const test: DatabaseConfig = _.merge({}, defaultKnexConfig, {
142
117
  connection: {
143
- database: `${config.database}_test`,
118
+ database: `${config.name}_test`,
144
119
  ...config.defaultOptions?.connection,
145
120
  },
146
121
  });
147
122
 
148
123
  const fixture_local = _.merge({}, defaultKnexConfig, {
149
124
  connection: {
150
- database: `${config.database}_fixture_local`,
125
+ database: `${config.name}_fixture_local`,
151
126
  ...config.defaultOptions?.connection,
152
127
  },
153
128
  });
@@ -163,11 +138,17 @@ class DBClass {
163
138
  devSlaveOptions
164
139
  );
165
140
  // NOTE: fixture remote는 default connection의 DB를 override해선 안됨.
166
- const fixture_remote = _.merge({}, defaultKnexConfig, devMasterOptions, {
167
- connection: {
168
- database: `${config.database}_fixture_remote`,
141
+ const fixture_remote = _.merge(
142
+ {},
143
+ defaultKnexConfig,
144
+ devMasterOptions,
145
+ {
146
+ connection: {
147
+ database: `${config.name}_fixture_remote`,
148
+ },
169
149
  },
170
- }, config.environments?.remote_fixture);
150
+ config.environments?.remote_fixture
151
+ );
171
152
 
172
153
  // 프로덕션 환경 설정
173
154
  const prodMasterOptions = config.environments?.production ?? {};
@@ -190,5 +171,17 @@ class DBClass {
190
171
  production_slave,
191
172
  };
192
173
  }
174
+
175
+ // Test 환경에서 트랜잭션 사용
176
+ public testTransaction: Knex.Transaction | null = null;
177
+ async createTestTransaction(): Promise<Knex.Transaction> {
178
+ const db = this.getDB("w");
179
+ this.testTransaction = await db.transaction();
180
+ return this.testTransaction;
181
+ }
182
+ async clearTestTransaction(): Promise<void> {
183
+ await this.testTransaction?.rollback();
184
+ this.testTransaction = null;
185
+ }
193
186
  }
194
187
  export const DB = new DBClass();
@@ -5,8 +5,8 @@ import { DatabaseSchemaExtend } from "../types/types";
5
5
  import chalk from "chalk";
6
6
  import { DBPreset } from "./db";
7
7
 
8
- type TableName<DBSchema extends DatabaseSchemaExtend> = Extract<
9
- keyof DBSchema,
8
+ type TableName<TSchema extends DatabaseSchemaExtend> = Extract<
9
+ keyof TSchema,
10
10
  string
11
11
  >;
12
12
 
@@ -17,7 +17,7 @@ export type TransactionalOptions = {
17
17
  };
18
18
 
19
19
  export class PuriWrapper<
20
- DBSchema extends DatabaseSchemaExtend = DatabaseSchemaExtend,
20
+ TSchema extends DatabaseSchemaExtend = DatabaseSchemaExtend,
21
21
  > {
22
22
  constructor(
23
23
  public knex: Knex,
@@ -27,60 +27,138 @@ export class PuriWrapper<
27
27
  raw(sql: string): Knex.Raw {
28
28
  return this.knex.raw(sql);
29
29
  }
30
- // 기존: 테이블로 시작
31
- table<TTable extends TableName<DBSchema>>(
30
+
31
+ // 테이블명으로 시작
32
+ from<TTable extends keyof TSchema>(
32
33
  tableName: TTable
33
- ): Puri<DBSchema, TTable> {
34
- return new Puri(this.knex, tableName as any);
34
+ ): Puri<
35
+ TSchema,
36
+ Record<TTable, TSchema[TTable]>,
37
+ Omit<TSchema[TTable], "__fulltext__">
38
+ >;
39
+ // 테이블명 + Alias로 시작
40
+ from<TTable extends keyof TSchema, TAlias extends string>(spec: {
41
+ [K in TAlias]: TTable;
42
+ }): Puri<
43
+ TSchema,
44
+ Record<TAlias, TSchema[TTable]>,
45
+ Omit<TSchema[TTable], "__fulltext__">
46
+ >;
47
+ // 서브쿼리로 시작
48
+ from<TAlias extends string, TSubResult>(spec: {
49
+ [K in TAlias]: Puri<TSchema, any, TSubResult>;
50
+ }): Puri<
51
+ TSchema,
52
+ Record<TAlias, TSubResult>,
53
+ Omit<TSubResult, "__fulltext__">
54
+ >;
55
+ from(spec: any): any {
56
+ return new Puri(this.knex, spec);
35
57
  }
36
58
 
37
- // 새로 추가: 서브쿼리로 시작
38
- fromSubquery<TSubResult, TAlias extends string>(
39
- subquery: Puri<DBSchema, any, any, TSubResult, any>,
40
- alias: TAlias extends string ? TAlias : never
41
- ): Puri<DBSchema, TAlias, TSubResult, TSubResult, {}> {
42
- return new Puri(this.knex, subquery, alias);
59
+ // 테이블명으로 시작
60
+ table<TTable extends keyof TSchema>(
61
+ tableName: TTable
62
+ ): Puri<
63
+ TSchema,
64
+ Record<TTable, TSchema[TTable]>,
65
+ Omit<TSchema[TTable], "__fulltext__">
66
+ >;
67
+ // 테이블명 + Alias로 시작
68
+ table<TTable extends keyof TSchema, TAlias extends string>(spec: {
69
+ [K in TAlias]: TTable;
70
+ }): Puri<
71
+ TSchema,
72
+ Record<TAlias, TSchema[TTable]>,
73
+ Omit<TSchema[TTable], "__fulltext__">
74
+ >;
75
+ // 서브쿼리로 시작
76
+ table<TAlias extends string, TSubResult>(spec: {
77
+ [K in TAlias]: Puri<TSchema, any, TSubResult>;
78
+ }): Puri<
79
+ TSchema,
80
+ Record<TAlias, TSubResult>,
81
+ Omit<TSubResult, "__fulltext__">
82
+ >;
83
+ table(spec: any): any {
84
+ return new Puri(this.knex, spec);
43
85
  }
44
86
 
45
87
  async transaction<T>(
46
88
  callback: (trx: PuriTransactionWrapper) => Promise<T>,
47
89
  options: TransactionalOptions = {}
48
90
  ): Promise<T> {
49
- const { isolation, readOnly } = options;
91
+ const { isolation, readOnly, dbPreset = "w" } = options;
92
+
93
+ // @transactional 데코레이터와 동일한 로직: 이미 트랜잭션 컨텍스트가 있는지 확인
94
+ const { DB } = await import("./db");
95
+ const existingContext = DB.transactionStorage.getStore();
96
+
97
+ // AsyncLocalStorage 컨텍스트가 없거나 해당 preset의 트랜잭션이 없으면 새로 시작
98
+ const startTransaction = async (
99
+ knex: Knex | Knex.Transaction,
100
+ upsertBuilder: UpsertBuilder
101
+ ) => {
102
+ return knex.transaction(
103
+ async (trx) => {
104
+ const trxWrapper = new PuriTransactionWrapper(trx, upsertBuilder);
105
+
106
+ // TransactionContext에 트랜잭션 저장
107
+ DB.getTransactionContext().setTransaction(dbPreset, trxWrapper);
108
+
109
+ try {
110
+ return await callback(trxWrapper);
111
+ } finally {
112
+ // 트랜잭션 제거
113
+ DB.getTransactionContext().deleteTransaction(dbPreset);
114
+ }
115
+ },
116
+ { isolationLevel: isolation, readOnly }
117
+ );
118
+ };
119
+
120
+ // AsyncLocalStorage 컨텍스트가 없으면 새로 생성
121
+ if (!existingContext) {
122
+ return DB.runWithTransaction(() =>
123
+ startTransaction(this.knex, this.upsertBuilder)
124
+ );
125
+ }
50
126
 
51
- return this.knex.transaction(
52
- async (trx) => {
53
- return callback(new PuriTransactionWrapper(trx, this.upsertBuilder));
54
- },
55
- { isolationLevel: isolation, readOnly }
56
- );
127
+ // 해당 preset의 트랜잭션이 이미 있으면 SAVEPOINT로 중첩 트랜잭션 생성
128
+ const existingTrx = existingContext.getTransaction(dbPreset);
129
+ if (existingTrx) {
130
+ return startTransaction(existingTrx.trx, existingTrx.upsertBuilder);
131
+ } else {
132
+ // 컨텍스트는 있지만 이 preset의 트랜잭션은 없는 경우 (같은 컨텍스트 내에서 실행)
133
+ return startTransaction(this.knex, this.upsertBuilder);
134
+ }
57
135
  }
58
136
 
59
- ubRegister<TTable extends TableName<DBSchema>>(
137
+ ubRegister<TTable extends TableName<TSchema>>(
60
138
  tableName: TTable,
61
139
  row: Partial<{
62
- [K in keyof DBSchema[TTable]]: DBSchema[TTable][K] | UBRef;
140
+ [K in keyof TSchema[TTable]]: TSchema[TTable][K] | UBRef;
63
141
  }>
64
142
  ): UBRef {
65
143
  return this.upsertBuilder.register(tableName, row);
66
144
  }
67
145
 
68
146
  ubUpsert(
69
- tableName: TableName<DBSchema>,
147
+ tableName: TableName<TSchema>,
70
148
  chunkSize?: number
71
149
  ): Promise<number[]> {
72
150
  return this.upsertBuilder.upsert(this.knex, tableName, chunkSize);
73
151
  }
74
152
 
75
153
  ubInsertOnly(
76
- tableName: TableName<DBSchema>,
154
+ tableName: TableName<TSchema>,
77
155
  chunkSize?: number
78
156
  ): Promise<number[]> {
79
157
  return this.upsertBuilder.insertOnly(this.knex, tableName, chunkSize);
80
158
  }
81
159
 
82
160
  ubUpsertOrInsert(
83
- tableName: TableName<DBSchema>,
161
+ tableName: TableName<TSchema>,
84
162
  mode: "upsert" | "insert",
85
163
  chunkSize?: number
86
164
  ): Promise<number[]> {
@@ -93,7 +171,7 @@ export class PuriWrapper<
93
171
  }
94
172
 
95
173
  ubUpdateBatch(
96
- tableName: TableName<DBSchema>,
174
+ tableName: TableName<TSchema>,
97
175
  options?: { chunkSize?: number; where?: string | string[] }
98
176
  ): Promise<void> {
99
177
  return this.upsertBuilder.updateBatch(this.knex, tableName, options);