sonamu 0.5.7 → 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 (358) 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.map +1 -1
  11. package/dist/api/decorators.js +142 -2
  12. package/dist/api/index.js +9 -2
  13. package/dist/api/sonamu.d.ts +8 -22
  14. package/dist/api/sonamu.d.ts.map +1 -1
  15. package/dist/api/sonamu.js +482 -2
  16. package/dist/bin/build-config.d.ts +2 -1
  17. package/dist/bin/build-config.d.ts.map +1 -1
  18. package/dist/bin/build-config.js +12 -2
  19. package/dist/bin/cli-wrapper.js +71 -2
  20. package/dist/bin/cli.js +418 -2
  21. package/dist/bin/hot-hook-register.d.ts +11 -0
  22. package/dist/bin/hot-hook-register.d.ts.map +1 -0
  23. package/dist/bin/hot-hook-register.js +21 -0
  24. package/dist/database/_batch_update.js +78 -2
  25. package/dist/database/base-model.js +247 -2
  26. package/dist/database/code-generator.js +53 -2
  27. package/dist/database/db.d.ts +2 -16
  28. package/dist/database/db.d.ts.map +1 -1
  29. package/dist/database/db.js +132 -2
  30. package/dist/database/knex-plugins/knex-on-duplicate-update.js +39 -2
  31. package/dist/database/puri-wrapper.js +109 -2
  32. package/dist/database/puri.d.ts +23 -16
  33. package/dist/database/puri.d.ts.map +1 -1
  34. package/dist/database/puri.js +539 -2
  35. package/dist/database/puri.types.d.ts +8 -3
  36. package/dist/database/puri.types.d.ts.map +1 -1
  37. package/dist/database/puri.types.js +3 -2
  38. package/dist/database/transaction-context.js +14 -2
  39. package/dist/database/upsert-builder.js +215 -2
  40. package/dist/entity/entity-manager.d.ts +3 -1
  41. package/dist/entity/entity-manager.d.ts.map +1 -1
  42. package/dist/entity/entity-manager.js +114 -2
  43. package/dist/entity/entity-utils.js +210 -2
  44. package/dist/entity/entity.d.ts.map +1 -1
  45. package/dist/entity/entity.js +651 -2
  46. package/dist/exceptions/error-handler.js +29 -2
  47. package/dist/exceptions/so-exceptions.js +85 -2
  48. package/dist/file-storage/driver.js +79 -2
  49. package/dist/file-storage/file-storage.js +75 -2
  50. package/dist/index.d.ts +2 -0
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +28 -2
  53. package/dist/migration/code-generation.js +558 -2
  54. package/dist/migration/migration-set.js +364 -2
  55. package/dist/migration/migrator.d.ts +0 -9
  56. package/dist/migration/migrator.d.ts.map +1 -1
  57. package/dist/migration/migrator.js +510 -2
  58. package/dist/migration/types.js +3 -2
  59. package/dist/naite/naite.d.ts +12 -0
  60. package/dist/naite/naite.d.ts.map +1 -0
  61. package/dist/naite/naite.js +72 -0
  62. package/dist/stream/index.js +3 -2
  63. package/dist/stream/sse.js +38 -2
  64. package/dist/syncer/api-parser.d.ts +20 -0
  65. package/dist/syncer/api-parser.d.ts.map +1 -0
  66. package/dist/syncer/api-parser.js +229 -0
  67. package/dist/syncer/checksum.d.ts +21 -0
  68. package/dist/syncer/checksum.d.ts.map +1 -0
  69. package/dist/syncer/checksum.js +98 -0
  70. package/dist/syncer/code-generator.d.ts +20 -0
  71. package/dist/syncer/code-generator.d.ts.map +1 -0
  72. package/dist/syncer/code-generator.js +141 -0
  73. package/dist/syncer/entity-operations.d.ts +17 -0
  74. package/dist/syncer/entity-operations.d.ts.map +1 -0
  75. package/dist/syncer/entity-operations.js +58 -0
  76. package/dist/syncer/file-patterns.d.ts +29 -0
  77. package/dist/syncer/file-patterns.d.ts.map +1 -0
  78. package/dist/syncer/file-patterns.js +38 -0
  79. package/dist/syncer/index.d.ts +6 -0
  80. package/dist/syncer/index.d.ts.map +1 -1
  81. package/dist/syncer/index.js +9 -2
  82. package/dist/syncer/module-loader.d.ts +35 -0
  83. package/dist/syncer/module-loader.d.ts.map +1 -0
  84. package/dist/syncer/module-loader.js +82 -0
  85. package/dist/syncer/syncer.d.ts +93 -108
  86. package/dist/syncer/syncer.d.ts.map +1 -1
  87. package/dist/syncer/syncer.js +375 -2
  88. package/dist/template/entity-converter.d.ts +14 -0
  89. package/dist/template/entity-converter.d.ts.map +1 -0
  90. package/dist/template/entity-converter.js +101 -0
  91. package/dist/template/helpers.d.ts +23 -0
  92. package/dist/template/helpers.d.ts.map +1 -0
  93. package/dist/template/helpers.js +64 -0
  94. package/dist/{templates → template/implementations}/entity.template.d.ts +3 -3
  95. package/dist/template/implementations/entity.template.d.ts.map +1 -0
  96. package/dist/template/implementations/entity.template.js +87 -0
  97. package/dist/{templates → template/implementations}/generated.template.d.ts +3 -3
  98. package/dist/template/implementations/generated.template.d.ts.map +1 -0
  99. package/dist/template/implementations/generated.template.js +232 -0
  100. package/dist/{templates → template/implementations}/generated_http.template.d.ts +3 -3
  101. package/dist/template/implementations/generated_http.template.d.ts.map +1 -0
  102. package/dist/template/implementations/generated_http.template.js +131 -0
  103. package/dist/{templates → template/implementations}/generated_sso.template.d.ts +3 -3
  104. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -0
  105. package/dist/template/implementations/generated_sso.template.js +105 -0
  106. package/dist/{templates → template/implementations}/init_types.template.d.ts +3 -3
  107. package/dist/template/implementations/init_types.template.d.ts.map +1 -0
  108. package/dist/template/implementations/init_types.template.js +38 -0
  109. package/dist/template/implementations/model.template.d.ts +17 -0
  110. package/dist/template/implementations/model.template.d.ts.map +1 -0
  111. package/dist/template/implementations/model.template.js +171 -0
  112. package/dist/{templates → template/implementations}/model_test.template.d.ts +3 -3
  113. package/dist/template/implementations/model_test.template.d.ts.map +1 -0
  114. package/dist/template/implementations/model_test.template.js +35 -0
  115. package/dist/{templates → template/implementations}/service.template.d.ts +6 -6
  116. package/dist/template/implementations/service.template.d.ts.map +1 -0
  117. package/dist/template/implementations/service.template.js +193 -0
  118. package/dist/{templates → template/implementations}/view_enums_buttonset.template.d.ts +3 -3
  119. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -0
  120. package/dist/template/implementations/view_enums_buttonset.template.js +31 -0
  121. package/dist/{templates → template/implementations}/view_enums_dropdown.template.d.ts +3 -4
  122. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -0
  123. package/dist/template/implementations/view_enums_dropdown.template.js +50 -0
  124. package/dist/{templates → template/implementations}/view_enums_select.template.d.ts +3 -3
  125. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -0
  126. package/dist/template/implementations/view_enums_select.template.js +55 -0
  127. package/dist/{templates → template/implementations}/view_form.template.d.ts +5 -5
  128. package/dist/template/implementations/view_form.template.d.ts.map +1 -0
  129. package/dist/template/implementations/view_form.template.js +337 -0
  130. package/dist/{templates → template/implementations}/view_id_all_select.template.d.ts +3 -3
  131. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -0
  132. package/dist/template/implementations/view_id_all_select.template.js +31 -0
  133. package/dist/{templates → template/implementations}/view_id_async_select.template.d.ts +3 -3
  134. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -0
  135. package/dist/template/implementations/view_id_async_select.template.js +105 -0
  136. package/dist/{templates → template/implementations}/view_list.template.d.ts +5 -13
  137. package/dist/template/implementations/view_list.template.d.ts.map +1 -0
  138. package/dist/template/implementations/view_list.template.js +465 -0
  139. package/dist/{templates → template/implementations}/view_list_columns.template.d.ts +3 -3
  140. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -0
  141. package/dist/template/implementations/view_list_columns.template.js +49 -0
  142. package/dist/{templates → template/implementations}/view_search_input.template.d.ts +3 -3
  143. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -0
  144. package/dist/template/implementations/view_search_input.template.js +64 -0
  145. package/dist/template/index.d.ts +5 -0
  146. package/dist/template/index.d.ts.map +1 -0
  147. package/dist/template/index.js +6 -0
  148. package/dist/template/template.d.ts +39 -0
  149. package/dist/template/template.d.ts.map +1 -0
  150. package/dist/template/template.js +47 -0
  151. package/dist/template/zod-converter.d.ts +18 -0
  152. package/dist/template/zod-converter.d.ts.map +1 -0
  153. package/dist/template/zod-converter.js +166 -0
  154. package/dist/testing/_relation-graph.js +80 -2
  155. package/dist/testing/fixture-manager.d.ts.map +1 -1
  156. package/dist/testing/fixture-manager.js +521 -2
  157. package/dist/types/types.d.ts +39 -40
  158. package/dist/types/types.d.ts.map +1 -1
  159. package/dist/types/types.js +289 -2
  160. package/dist/typings/knex.d.js +3 -2
  161. package/dist/utils/async-utils.d.ts +7 -0
  162. package/dist/utils/async-utils.d.ts.map +1 -1
  163. package/dist/utils/async-utils.js +57 -2
  164. package/dist/utils/console-util.d.ts +2 -0
  165. package/dist/utils/console-util.d.ts.map +1 -0
  166. package/dist/utils/console-util.js +6 -0
  167. package/dist/utils/controller.js +26 -2
  168. package/dist/utils/esm-utils.d.ts +45 -0
  169. package/dist/utils/esm-utils.d.ts.map +1 -0
  170. package/dist/utils/esm-utils.js +56 -0
  171. package/dist/utils/fs-utils.js +17 -2
  172. package/dist/utils/lodash-able.js +6 -2
  173. package/dist/utils/model.js +22 -2
  174. package/dist/utils/path-utils.d.ts +89 -0
  175. package/dist/utils/path-utils.d.ts.map +1 -0
  176. package/dist/utils/path-utils.js +60 -0
  177. package/dist/utils/process-utils.d.ts +13 -0
  178. package/dist/utils/process-utils.d.ts.map +1 -0
  179. package/dist/utils/process-utils.js +36 -0
  180. package/dist/utils/sql-parser.js +35 -2
  181. package/dist/utils/utils.d.ts +4 -7
  182. package/dist/utils/utils.d.ts.map +1 -1
  183. package/dist/utils/utils.js +33 -2
  184. package/dist/utils/zod-error.d.ts.map +1 -1
  185. package/dist/utils/zod-error.js +19 -2
  186. package/package.json +21 -8
  187. package/src/api/code-converters.ts +2 -2
  188. package/src/api/config.ts +142 -0
  189. package/src/api/context.ts +1 -0
  190. package/src/api/decorators.ts +1 -0
  191. package/src/api/sonamu.ts +81 -67
  192. package/src/bin/build-config.ts +2 -1
  193. package/src/bin/cli-wrapper.ts +10 -3
  194. package/src/bin/cli.ts +108 -56
  195. package/src/bin/hot-hook-register.ts +22 -0
  196. package/src/database/base-model.ts +1 -1
  197. package/src/database/code-generator.ts +1 -1
  198. package/src/database/db.ts +10 -52
  199. package/src/database/puri.ts +78 -53
  200. package/src/database/puri.types.ts +18 -5
  201. package/src/database/upsert-builder.ts +1 -1
  202. package/src/entity/entity-manager.ts +19 -15
  203. package/src/entity/entity.ts +4 -3
  204. package/src/index.ts +2 -0
  205. package/src/migration/code-generation.ts +1 -1
  206. package/src/migration/migration-set.ts +1 -1
  207. package/src/migration/migrator.ts +23 -152
  208. package/src/naite/naite.ts +70 -0
  209. package/src/syncer/api-parser.ts +299 -0
  210. package/src/syncer/checksum.ts +152 -0
  211. package/src/syncer/code-generator.ts +202 -0
  212. package/src/syncer/entity-operations.ts +68 -0
  213. package/src/syncer/file-patterns.ts +56 -0
  214. package/src/syncer/index.ts +6 -0
  215. package/src/syncer/module-loader.ts +125 -0
  216. package/src/syncer/syncer.ts +363 -1420
  217. package/src/template/entity-converter.ts +123 -0
  218. package/src/template/helpers.ts +84 -0
  219. package/src/{templates → template/implementations}/entity.template.ts +4 -4
  220. package/src/{templates → template/implementations}/generated.template.ts +9 -9
  221. package/src/{templates → template/implementations}/generated_http.template.ts +9 -6
  222. package/src/{templates → template/implementations}/generated_sso.template.ts +7 -7
  223. package/src/{templates → template/implementations}/init_types.template.ts +4 -4
  224. package/src/{templates → template/implementations}/model.template.ts +9 -9
  225. package/src/{templates → template/implementations}/model_test.template.ts +5 -5
  226. package/src/{templates → template/implementations}/service.template.ts +19 -11
  227. package/src/{templates → template/implementations}/view_enums_buttonset.template.ts +3 -3
  228. package/src/{templates → template/implementations}/view_enums_dropdown.template.ts +5 -21
  229. package/src/{templates → template/implementations}/view_enums_select.template.ts +4 -4
  230. package/src/{templates → template/implementations}/view_form.template.ts +11 -13
  231. package/src/{templates → template/implementations}/view_id_all_select.template.ts +3 -3
  232. package/src/{templates → template/implementations}/view_id_async_select.template.ts +3 -3
  233. package/src/{templates → template/implementations}/view_list.template.ts +13 -64
  234. package/src/{templates → template/implementations}/view_list_columns.template.ts +3 -3
  235. package/src/{templates → template/implementations}/view_search_input.template.ts +3 -3
  236. package/src/template/index.ts +4 -0
  237. package/src/template/template.ts +86 -0
  238. package/src/template/zod-converter.ts +219 -0
  239. package/src/testing/fixture-manager.ts +8 -1
  240. package/src/types/types.ts +38 -61
  241. package/src/utils/async-utils.ts +17 -0
  242. package/src/utils/console-util.ts +4 -0
  243. package/src/utils/esm-utils.ts +69 -0
  244. package/src/utils/path-utils.ts +102 -0
  245. package/src/utils/process-utils.ts +46 -0
  246. package/src/utils/sql-parser.ts +1 -1
  247. package/src/utils/utils.ts +14 -40
  248. package/src/utils/zod-error.ts +0 -1
  249. package/dist/api/base-frame.js.map +0 -1
  250. package/dist/api/caster.js.map +0 -1
  251. package/dist/api/code-converters.js.map +0 -1
  252. package/dist/api/context.js.map +0 -1
  253. package/dist/api/decorators.js.map +0 -1
  254. package/dist/api/index.js.map +0 -1
  255. package/dist/api/sonamu.js.map +0 -1
  256. package/dist/bin/build-config.js.map +0 -1
  257. package/dist/bin/cli-wrapper.js.map +0 -1
  258. package/dist/bin/cli.js.map +0 -1
  259. package/dist/database/_batch_update.js.map +0 -1
  260. package/dist/database/base-model.js.map +0 -1
  261. package/dist/database/code-generator.js.map +0 -1
  262. package/dist/database/db.js.map +0 -1
  263. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +0 -1
  264. package/dist/database/puri-wrapper.js.map +0 -1
  265. package/dist/database/puri.js.map +0 -1
  266. package/dist/database/puri.types.js.map +0 -1
  267. package/dist/database/transaction-context.js.map +0 -1
  268. package/dist/database/upsert-builder.js.map +0 -1
  269. package/dist/entity/entity-manager.js.map +0 -1
  270. package/dist/entity/entity-utils.js.map +0 -1
  271. package/dist/entity/entity.js.map +0 -1
  272. package/dist/exceptions/error-handler.js.map +0 -1
  273. package/dist/exceptions/so-exceptions.js.map +0 -1
  274. package/dist/file-storage/driver.js.map +0 -1
  275. package/dist/file-storage/file-storage.js.map +0 -1
  276. package/dist/index.js.map +0 -1
  277. package/dist/migration/code-generation.js.map +0 -1
  278. package/dist/migration/migration-set.js.map +0 -1
  279. package/dist/migration/migrator.js.map +0 -1
  280. package/dist/migration/types.js.map +0 -1
  281. package/dist/stream/index.js.map +0 -1
  282. package/dist/stream/sse.js.map +0 -1
  283. package/dist/syncer/index.js.map +0 -1
  284. package/dist/syncer/syncer.js.map +0 -1
  285. package/dist/templates/base-template.d.ts +0 -13
  286. package/dist/templates/base-template.d.ts.map +0 -1
  287. package/dist/templates/base-template.js +0 -2
  288. package/dist/templates/base-template.js.map +0 -1
  289. package/dist/templates/entity.template.d.ts.map +0 -1
  290. package/dist/templates/entity.template.js +0 -2
  291. package/dist/templates/entity.template.js.map +0 -1
  292. package/dist/templates/generated.template.d.ts.map +0 -1
  293. package/dist/templates/generated.template.js +0 -2
  294. package/dist/templates/generated.template.js.map +0 -1
  295. package/dist/templates/generated_http.template.d.ts.map +0 -1
  296. package/dist/templates/generated_http.template.js +0 -2
  297. package/dist/templates/generated_http.template.js.map +0 -1
  298. package/dist/templates/generated_sso.template.d.ts.map +0 -1
  299. package/dist/templates/generated_sso.template.js +0 -2
  300. package/dist/templates/generated_sso.template.js.map +0 -1
  301. package/dist/templates/index.d.ts +0 -2
  302. package/dist/templates/index.d.ts.map +0 -1
  303. package/dist/templates/index.js +0 -2
  304. package/dist/templates/index.js.map +0 -1
  305. package/dist/templates/init_types.template.d.ts.map +0 -1
  306. package/dist/templates/init_types.template.js +0 -2
  307. package/dist/templates/init_types.template.js.map +0 -1
  308. package/dist/templates/model.template.d.ts +0 -17
  309. package/dist/templates/model.template.d.ts.map +0 -1
  310. package/dist/templates/model.template.js +0 -2
  311. package/dist/templates/model.template.js.map +0 -1
  312. package/dist/templates/model_test.template.d.ts.map +0 -1
  313. package/dist/templates/model_test.template.js +0 -2
  314. package/dist/templates/model_test.template.js.map +0 -1
  315. package/dist/templates/service.template.d.ts.map +0 -1
  316. package/dist/templates/service.template.js +0 -2
  317. package/dist/templates/service.template.js.map +0 -1
  318. package/dist/templates/view_enums_buttonset.template.d.ts.map +0 -1
  319. package/dist/templates/view_enums_buttonset.template.js +0 -2
  320. package/dist/templates/view_enums_buttonset.template.js.map +0 -1
  321. package/dist/templates/view_enums_dropdown.template.d.ts.map +0 -1
  322. package/dist/templates/view_enums_dropdown.template.js +0 -2
  323. package/dist/templates/view_enums_dropdown.template.js.map +0 -1
  324. package/dist/templates/view_enums_select.template.d.ts.map +0 -1
  325. package/dist/templates/view_enums_select.template.js +0 -2
  326. package/dist/templates/view_enums_select.template.js.map +0 -1
  327. package/dist/templates/view_form.template.d.ts.map +0 -1
  328. package/dist/templates/view_form.template.js +0 -2
  329. package/dist/templates/view_form.template.js.map +0 -1
  330. package/dist/templates/view_id_all_select.template.d.ts.map +0 -1
  331. package/dist/templates/view_id_all_select.template.js +0 -2
  332. package/dist/templates/view_id_all_select.template.js.map +0 -1
  333. package/dist/templates/view_id_async_select.template.d.ts.map +0 -1
  334. package/dist/templates/view_id_async_select.template.js +0 -2
  335. package/dist/templates/view_id_async_select.template.js.map +0 -1
  336. package/dist/templates/view_list.template.d.ts.map +0 -1
  337. package/dist/templates/view_list.template.js +0 -2
  338. package/dist/templates/view_list.template.js.map +0 -1
  339. package/dist/templates/view_list_columns.template.d.ts.map +0 -1
  340. package/dist/templates/view_list_columns.template.js +0 -2
  341. package/dist/templates/view_list_columns.template.js.map +0 -1
  342. package/dist/templates/view_search_input.template.d.ts.map +0 -1
  343. package/dist/templates/view_search_input.template.js +0 -2
  344. package/dist/templates/view_search_input.template.js.map +0 -1
  345. package/dist/testing/_relation-graph.js.map +0 -1
  346. package/dist/testing/fixture-manager.js.map +0 -1
  347. package/dist/types/types.js.map +0 -1
  348. package/dist/typings/knex.d.js.map +0 -1
  349. package/dist/utils/async-utils.js.map +0 -1
  350. package/dist/utils/controller.js.map +0 -1
  351. package/dist/utils/fs-utils.js.map +0 -1
  352. package/dist/utils/lodash-able.js.map +0 -1
  353. package/dist/utils/model.js.map +0 -1
  354. package/dist/utils/sql-parser.js.map +0 -1
  355. package/dist/utils/utils.js.map +0 -1
  356. package/dist/utils/zod-error.js.map +0 -1
  357. package/src/templates/base-template.ts +0 -19
  358. package/src/templates/index.ts +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/database/puri-wrapper.ts"],"sourcesContent":["import { Knex } from \"knex\";\nimport { Puri } from \"./puri\";\nimport { UBRef, UpsertBuilder } from \"./upsert-builder\";\nimport { DatabaseSchemaExtend } from \"../types/types\";\nimport chalk from \"chalk\";\nimport { DBPreset } from \"./db\";\n\ntype TableName<TSchema extends DatabaseSchemaExtend> = Extract<\n keyof TSchema,\n string\n>;\n\nexport type TransactionalOptions = {\n isolation?: Exclude<Knex.IsolationLevels, \"snapshot\">; // snapshot: mssql only\n dbPreset?: DBPreset;\n readOnly?: boolean;\n};\n\nexport class PuriWrapper<\n TSchema extends DatabaseSchemaExtend = DatabaseSchemaExtend,\n> {\n constructor(\n public knex: Knex,\n public upsertBuilder: UpsertBuilder\n ) {}\n\n raw(sql: string): Knex.Raw {\n return this.knex.raw(sql);\n }\n\n // 테이블명으로 시작\n from<TTable extends keyof TSchema>(\n tableName: TTable\n ): Puri<\n TSchema,\n Record<TTable, TSchema[TTable]>,\n Omit<TSchema[TTable], \"__fulltext__\">\n >;\n // 테이블명 + Alias로 시작\n from<TTable extends keyof TSchema, TAlias extends string>(spec: {\n [K in TAlias]: TTable;\n }): Puri<\n TSchema,\n Record<TAlias, TSchema[TTable]>,\n Omit<TSchema[TTable], \"__fulltext__\">\n >;\n // 서브쿼리로 시작\n from<TAlias extends string, TSubResult>(spec: {\n [K in TAlias]: Puri<TSchema, any, TSubResult>;\n }): Puri<\n TSchema,\n Record<TAlias, TSubResult>,\n Omit<TSubResult, \"__fulltext__\">\n >;\n from(spec: any): any {\n return new Puri(this.knex, spec);\n }\n\n // 테이블명으로 시작\n table<TTable extends keyof TSchema>(\n tableName: TTable\n ): Puri<\n TSchema,\n Record<TTable, TSchema[TTable]>,\n Omit<TSchema[TTable], \"__fulltext__\">\n >;\n // 테이블명 + Alias로 시작\n table<TTable extends keyof TSchema, TAlias extends string>(spec: {\n [K in TAlias]: TTable;\n }): Puri<\n TSchema,\n Record<TAlias, TSchema[TTable]>,\n Omit<TSchema[TTable], \"__fulltext__\">\n >;\n // 서브쿼리로 시작\n table<TAlias extends string, TSubResult>(spec: {\n [K in TAlias]: Puri<TSchema, any, TSubResult>;\n }): Puri<\n TSchema,\n Record<TAlias, TSubResult>,\n Omit<TSubResult, \"__fulltext__\">\n >;\n table(spec: any): any {\n return new Puri(this.knex, spec);\n }\n\n async transaction<T>(\n callback: (trx: PuriTransactionWrapper) => Promise<T>,\n options: TransactionalOptions = {}\n ): Promise<T> {\n const { isolation, readOnly, dbPreset = \"w\" } = options;\n\n // @transactional 데코레이터와 동일한 로직: 이미 트랜잭션 컨텍스트가 있는지 확인\n const { DB } = await import(\"./db\");\n const existingContext = DB.transactionStorage.getStore();\n\n // AsyncLocalStorage 컨텍스트가 없거나 해당 preset의 트랜잭션이 없으면 새로 시작\n const startTransaction = async (\n knex: Knex | Knex.Transaction,\n upsertBuilder: UpsertBuilder\n ) => {\n return knex.transaction(\n async (trx) => {\n const trxWrapper = new PuriTransactionWrapper(trx, upsertBuilder);\n\n // TransactionContext에 트랜잭션 저장\n DB.getTransactionContext().setTransaction(dbPreset, trxWrapper);\n\n try {\n return await callback(trxWrapper);\n } finally {\n // 트랜잭션 제거\n DB.getTransactionContext().deleteTransaction(dbPreset);\n }\n },\n { isolationLevel: isolation, readOnly }\n );\n };\n\n // AsyncLocalStorage 컨텍스트가 없으면 새로 생성\n if (!existingContext) {\n return DB.runWithTransaction(() =>\n startTransaction(this.knex, this.upsertBuilder)\n );\n }\n\n // 해당 preset의 트랜잭션이 이미 있으면 SAVEPOINT로 중첩 트랜잭션 생성\n const existingTrx = existingContext.getTransaction(dbPreset);\n if (existingTrx) {\n return startTransaction(existingTrx.trx, existingTrx.upsertBuilder);\n } else {\n // 컨텍스트는 있지만 이 preset의 트랜잭션은 없는 경우 (같은 컨텍스트 내에서 실행)\n return startTransaction(this.knex, this.upsertBuilder);\n }\n }\n\n ubRegister<TTable extends TableName<TSchema>>(\n tableName: TTable,\n row: Partial<{\n [K in keyof TSchema[TTable]]: TSchema[TTable][K] | UBRef;\n }>\n ): UBRef {\n return this.upsertBuilder.register(tableName, row);\n }\n\n ubUpsert(\n tableName: TableName<TSchema>,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertBuilder.upsert(this.knex, tableName, chunkSize);\n }\n\n ubInsertOnly(\n tableName: TableName<TSchema>,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertBuilder.insertOnly(this.knex, tableName, chunkSize);\n }\n\n ubUpsertOrInsert(\n tableName: TableName<TSchema>,\n mode: \"upsert\" | \"insert\",\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertBuilder.upsertOrInsert(\n this.knex,\n tableName,\n mode,\n chunkSize\n );\n }\n\n ubUpdateBatch(\n tableName: TableName<TSchema>,\n options?: { chunkSize?: number; where?: string | string[] }\n ): Promise<void> {\n return this.upsertBuilder.updateBatch(this.knex, tableName, options);\n }\n\n // 트랜잭션 연결 테스트용\n async debugTransaction() {\n const info = await this.getTransactionInfo();\n console.log(`${chalk.cyan(\"[Puri Transaction]\")} ${chalk.magenta(info)}`);\n }\n\n private async getTransactionInfo(): Promise<string> {\n // 연결 ID 조회\n const [connectionIdRows] = await this.knex.raw(\n `SELECT CONNECTION_ID() as connection_id`\n );\n const connectionId = connectionIdRows[0].connection_id;\n\n // 트랜잭션 정보 조회\n const [trxRows] = await this.knex.raw(`\n SELECT STATE, ISOLATION_LEVEL, THREAD_ID, EVENT_ID\n FROM performance_schema.events_transactions_current\n WHERE THREAD_ID = \n (SELECT THREAD_ID\n FROM performance_schema.threads \n WHERE PROCESSLIST_ID = CONNECTION_ID())\n `);\n\n if (trxRows.length > 0 && trxRows[0].STATE !== \"COMMITTED\") {\n const trx = trxRows[0];\n return `In Transaction, ConnID: ${connectionId}, ThreadID: ${trx.THREAD_ID}, EventID: ${trx.EVENT_ID}, InnoDB TRX: ${trx.STATE}(${trx.ISOLATION_LEVEL})`;\n } else {\n return `Not in Transaction, ConnID: ${connectionId}`;\n }\n }\n}\n\nexport class PuriTransactionWrapper extends PuriWrapper {\n constructor(\n public trx: Knex.Transaction,\n public upsertBuilder: UpsertBuilder\n ) {\n super(trx, upsertBuilder);\n }\n\n async rollback(): Promise<void> {\n await this.trx.rollback();\n }\n\n async commit(): Promise<void> {\n await this.trx.commit();\n }\n}\n"],"names":["PuriTransactionWrapper","PuriWrapper","knex","upsertBuilder","raw","sql","from","spec","Puri","table","transaction","callback","options","isolation","readOnly","dbPreset","DB","existingContext","startTransaction","existingTrx","transactionStorage","getStore","trx","trxWrapper","getTransactionContext","setTransaction","deleteTransaction","isolationLevel","runWithTransaction","getTransaction","ubRegister","tableName","row","register","ubUpsert","chunkSize","upsert","ubInsertOnly","insertOnly","ubUpsertOrInsert","mode","upsertOrInsert","ubUpdateBatch","updateBatch","debugTransaction","info","getTransactionInfo","console","log","chalk","cyan","magenta","connectionIdRows","connectionId","trxRows","connection_id","length","STATE","THREAD_ID","EVENT_ID","ISOLATION_LEVEL","rollback","commit"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/database/puri.ts"],"sourcesContent":["import type { Knex } from \"knex\";\nimport type {\n AvailableColumns,\n SelectObject,\n ParseSelectObject,\n WhereCondition,\n ComparisonOperator,\n ExtractColumnType,\n SqlExpression,\n Expand,\n FulltextColumns,\n ResultAvailableColumns,\n InsertData,\n SingleTableValue,\n} from \"./puri.types\";\nimport chalk from \"chalk\";\nimport assert from \"assert\";\n\nexport class Puri<\n TSchema,\n TTables extends Record<string, any>,\n TResult,\n TResolved = Expand<TResult>[],\n> {\n private knexQuery: Knex.QueryBuilder;\n\n // 생성자 시그니처들\n constructor(knex: Knex, tableName: string);\n constructor(\n knex: Knex,\n tableSpec: Record<string, string | Puri<TSchema, any, any>>\n );\n constructor(\n private knex: Knex,\n tableNameOrSpec: any\n ) {\n if (typeof tableNameOrSpec === \"string\") {\n // Case: new Puri(knex, \"users\")\n this.knexQuery = this.knex(tableNameOrSpec).from(tableNameOrSpec);\n } else if (typeof tableNameOrSpec === \"object\") {\n const entries = Object.entries(tableNameOrSpec);\n if (entries.length !== 1) {\n throw new Error(\"Table spec must have exactly one entry\");\n }\n assert(entries[0]);\n const [alias, spec] = entries[0];\n if (typeof spec === \"string\") {\n this.knexQuery = this.knex(spec).from({ [alias]: spec });\n } else if (spec instanceof Puri) {\n const subqueryBuilder = spec.raw();\n this.knexQuery = this.knex.from(subqueryBuilder.as(alias));\n } else {\n throw new Error(\"Invalid table specification\");\n }\n } else {\n throw new Error(\"Invalid table specification\");\n }\n }\n\n // Static SQL helper functions for SELECT\n static count(column: string = \"*\"): SqlExpression<\"number\"> {\n return {\n _type: \"sql_expression\",\n _return: \"number\",\n _sql: `COUNT(${column})`,\n };\n }\n static sum(column: string): SqlExpression<\"number\"> {\n return {\n _type: \"sql_expression\",\n _return: \"number\",\n _sql: `SUM(${column})`,\n };\n }\n static avg(column: string): SqlExpression<\"number\"> {\n return {\n _type: \"sql_expression\",\n _return: \"number\",\n _sql: `AVG(${column})`,\n };\n }\n static max(column: string): SqlExpression<\"number\"> {\n return {\n _type: \"sql_expression\",\n _return: \"number\",\n _sql: `MAX(${column})`,\n };\n }\n static min(column: string): SqlExpression<\"number\"> {\n return {\n _type: \"sql_expression\",\n _return: \"number\",\n _sql: `MIN(${column})`,\n };\n }\n static concat(...args: string[]): SqlExpression<\"string\"> {\n return {\n _type: \"sql_expression\",\n _return: \"string\",\n _sql: `CONCAT(${args.join(\", \")})`,\n };\n }\n static upper(column: string): SqlExpression<\"string\"> {\n return {\n _type: \"sql_expression\",\n _return: \"string\",\n _sql: `UPPER(${column})`,\n };\n }\n static lower(column: string): SqlExpression<\"string\"> {\n return {\n _type: \"sql_expression\",\n _return: \"string\",\n _sql: `LOWER(${column})`,\n };\n }\n\n // Raw functions for SELECT\n static rawString(sql: string): SqlExpression<\"string\"> {\n return { _type: \"sql_expression\", _return: \"string\", _sql: sql };\n }\n static rawNumber(sql: string): SqlExpression<\"number\"> {\n return { _type: \"sql_expression\", _return: \"number\", _sql: sql };\n }\n static rawBoolean(sql: string): SqlExpression<\"boolean\"> {\n return { _type: \"sql_expression\", _return: \"boolean\", _sql: sql };\n }\n static rawDate(sql: string): SqlExpression<\"date\"> {\n return { _type: \"sql_expression\", _return: \"date\", _sql: sql };\n }\n\n // SELECT\n select<TSelect extends SelectObject<TTables>>(\n selectObj: TSelect\n ): Puri<TSchema, TTables, ParseSelectObject<TTables, TSelect>> {\n const selectClauses: (string | Knex.Raw)[] = [];\n\n for (const [alias, columnOrFunction] of Object.entries(selectObj)) {\n if (\n typeof columnOrFunction === \"object\" &&\n columnOrFunction._type === \"sql_expression\"\n ) {\n // SQL 함수인 경우\n selectClauses.push(\n this.knex.raw(`${columnOrFunction._sql} as ${alias}`)\n );\n } else {\n // 일반 컬럼인 경우\n const columnPath = columnOrFunction as string;\n if (alias === columnPath) {\n // alias와 컬럼명이 같으면 alias 생략\n selectClauses.push(columnPath);\n } else {\n // alias 지정\n selectClauses.push(`${columnPath} as ${alias}`);\n }\n }\n }\n\n this.knexQuery.select(selectClauses);\n return this as any;\n }\n\n // SELECT *\n selectAll(): this {\n this.knexQuery.select(\"*\");\n return this as any;\n }\n\n // JOIN: 서브쿼리 + Alias\n join<TJoinAlias extends string, TSubResult>(\n tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },\n left: AvailableColumns<TTables>,\n right: `${TJoinAlias}.${keyof TSubResult & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult\n TResult\n >;\n // JOIN: 테이블 + Alias\n join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(\n tableSpec: { [K in TJoinAlias]: TJoinTable },\n left: AvailableColumns<TTables>,\n right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!\n TResult\n >;\n // JOIN: 테이블명\n join<TJoinTable extends keyof TSchema>(\n tableName: TJoinTable,\n left: AvailableColumns<TTables>,\n right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키\n TResult\n >;\n // JOIN: 서브쿼리 + Alias + 콜백\n join<TJoinAlias extends string, TSubResult>(\n tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;\n // JOIN: 테이블 + Alias + 콜백\n join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(\n tableSpec: { [K in TJoinAlias]: TJoinTable },\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;\n // JOIN: 테이블명 + 콜백\n join<TJoinTable extends keyof TSchema>(\n tableName: TJoinTable,\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;\n // JOIN 실제 구현\n join(tableNameOrSpec: any, ...args: any[]): any {\n return this.__commonJoin(\"join\", tableNameOrSpec, ...args);\n }\n\n // LEFT JOIN: 서브쿼리 + Alias\n leftJoin<TJoinAlias extends string, TSubResult>(\n tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },\n left: AvailableColumns<TTables>,\n right: `${TJoinAlias}.${keyof TSubResult & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult\n TResult\n >;\n // LEFT JOIN: 테이블 + Alias\n leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(\n tableSpec: { [K in TJoinAlias]: TJoinTable },\n left: AvailableColumns<TTables>,\n right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!\n TResult\n >;\n // LEFT JOIN: 테이블명\n leftJoin<TJoinTable extends keyof TSchema>(\n tableName: TJoinTable,\n left: AvailableColumns<TTables>,\n right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`\n ): Puri<\n TSchema,\n TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키\n TResult\n >;\n // LEFT JOIN: 서브쿼리 + Alias + 콜백\n leftJoin<TJoinAlias extends string, TSubResult>(\n tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;\n // LEFT JOIN: 테이블 + Alias + 콜백\n leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(\n tableSpec: { [K in TJoinAlias]: TJoinTable },\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;\n // LEFT JOIN: 테이블명 + 콜백\n leftJoin<TJoinTable extends keyof TSchema>(\n tableName: TJoinTable,\n callback: (\n j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>\n ) => void\n ): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;\n // LEFT JOIN 실제 구현\n leftJoin(tableNameOrSpec: any, ...args: any[]): any {\n return this.__commonJoin(\"leftJoin\", tableNameOrSpec, ...args);\n }\n\n __commonJoin(\n joinType: \"join\" | \"leftJoin\",\n tableNameOrSpec: any,\n ...args: any[]\n ): this {\n if (typeof tableNameOrSpec === \"string\") {\n // Case 1: join(\"posts\", ...)\n const tableName = tableNameOrSpec;\n\n if (args.length === 1 && typeof args[0] === \"function\") {\n // join(\"posts\", callback)\n const callback = args[0];\n this.knexQuery[joinType](tableName, (joinClause) => {\n callback(new JoinClauseGroup(joinClause));\n });\n } else {\n // join(\"posts\", left, right)\n const [left, right] = args;\n this.knexQuery[joinType](tableName, left, right);\n }\n } else if (typeof tableNameOrSpec === \"object\") {\n // Case 2: join({ alias: \"table\" }, ...) or join({ alias: subquery }, ...)\n const entries = Object.entries(tableNameOrSpec);\n if (entries.length !== 1) {\n throw new Error(\"Table spec must have exactly one entry\");\n }\n assert(entries[0]);\n const [[alias, spec]] = entries;\n\n if (typeof spec === \"string\") {\n // 테이블: join({ p: \"posts\" }, ...)\n if (args.length === 1 && typeof args[0] === \"function\") {\n // Callback\n const callback = args[0];\n this.knexQuery[joinType]({ [alias]: spec }, (joinClause) => {\n callback(new JoinClauseGroup(joinClause));\n });\n } else {\n // Simple\n const [left, right] = args;\n this.knexQuery[joinType]({ [alias]: spec }, left, right);\n }\n } else if (spec instanceof Puri) {\n // 서브쿼리: join({ sq: subquery }, ...)\n if (args.length === 1 && typeof args[0] === \"function\") {\n // Callback\n const callback = args[0];\n this.knexQuery[joinType](spec.raw().as(alias), (joinClause) => {\n callback(new JoinClauseGroup(joinClause));\n });\n } else {\n // Simple\n const [left, right] = args;\n this.knexQuery[joinType](spec.raw().as(alias), left, right);\n }\n } else {\n throw new Error(\"Invalid table specification\");\n }\n } else {\n throw new Error(\"Invalid arguments\");\n }\n\n return this;\n }\n\n // WHERE: 객체 - 사용: .where({ \"u.id\": 1, \"u.status\": \"active\" })\n where(conditions: WhereCondition<TTables>): this;\n // WHERE: 컬럼 - 사용: .where(\"u.id\", 1)\n where<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n // WHERE: 컬럼 - 사용: .where(\"u.id\", \">\", 10)\n where<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n operator: ComparisonOperator,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n // WHERE: 컬럼 - 사용: .where(\"u.id\", \"like\", \"%test%\")\n where(columnOrConditions: any, operatorOrValue?: any, value?: any): this {\n if (typeof columnOrConditions === \"object\") {\n this.knexQuery.where(columnOrConditions);\n } else if (arguments.length === 2) {\n if (operatorOrValue === null) {\n this.knexQuery.whereNull(columnOrConditions);\n return this;\n }\n this.knexQuery.where(columnOrConditions, operatorOrValue);\n } else if (arguments.length === 3) {\n if (value === null) {\n if (operatorOrValue === \"!=\") {\n this.knexQuery.whereNotNull(columnOrConditions);\n return this;\n } else if (operatorOrValue === \"=\") {\n this.knexQuery.whereNull(columnOrConditions);\n return this;\n }\n }\n this.knexQuery.where(columnOrConditions, operatorOrValue, value);\n } else {\n this.knexQuery.where(columnOrConditions);\n }\n return this;\n }\n\n // WHERE IN\n whereIn<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n values: ExtractColumnType<TTables, TColumn & string>[]\n ): Puri<TSchema, TTables, TResult> {\n this.knexQuery.whereIn(column, values);\n return this as any;\n }\n\n // WHERE NOT IN\n whereNotIn<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n values: ExtractColumnType<TTables, TColumn & string>[]\n ): Puri<TSchema, TTables, TResult> {\n this.knexQuery.whereIn(column, values);\n return this as any;\n }\n\n // WHERE MATCH\n whereMatch<TColumn extends FulltextColumns<TTables>>(\n column: TColumn,\n value: string\n ): this {\n this.knexQuery.whereRaw(`MATCH (${String(column)}) AGAINST (?)`, [value]);\n return this;\n }\n\n // WHERE 괄호 그룹핑\n whereGroup(callback: (g: WhereGroup<TTables>) => void): this {\n this.knexQuery.where((builder) => {\n const group = new WhereGroup<TTables>(builder);\n callback(group);\n });\n return this;\n }\n orWhereGroup(callback: (g: WhereGroup<TTables>) => void): this {\n this.knexQuery.orWhere((builder) => {\n const group = new WhereGroup<TTables>(builder);\n callback(group);\n });\n return this;\n }\n\n // ORDER BY\n orderBy<TColumn extends ResultAvailableColumns<TTables, TResult>>(\n column: TColumn,\n direction: \"asc\" | \"desc\"\n ): this;\n orderBy(column: string, direction: \"asc\" | \"desc\" = \"asc\"): this {\n this.knexQuery.orderBy(column, direction);\n return this;\n }\n\n // 기본 쿼리 메서드들\n limit(count: number): this {\n this.knexQuery.limit(count);\n return this;\n }\n\n offset(count: number): this {\n this.knexQuery.offset(count);\n return this;\n }\n\n // GROUP BY\n groupBy<TColumns extends ResultAvailableColumns<TTables, TResult>>(\n ...columns: TColumns[]\n ): this;\n groupBy(...columns: string[]): this {\n this.knexQuery.groupBy(...(columns as string[]));\n return this;\n }\n\n // HAVING\n having(condition: string): this;\n having<TColumn extends ResultAvailableColumns<TTables, TResult>>(\n column: TColumn,\n operator: ComparisonOperator,\n value: any\n ): this;\n // HAVING 구현\n having(...conditions: any[]): this {\n if (conditions.length === 1) {\n // having(\"COUNT(*) > 10\")\n this.knexQuery.having(conditions[0]);\n } else if (conditions.length === 3) {\n // having(\"count\", \">\", 10)\n this.knexQuery.having(conditions[0], conditions[1], conditions[2]);\n } else {\n throw new Error(\"Invalid having arguments\");\n }\n return this;\n }\n\n // 실행 메서드들 - thenable 구현\n then<TResult1 = TResolved, TResult2 = never>(\n onfulfilled?:\n | ((value: TResolved) => TResult1 | PromiseLike<TResult1>)\n | null,\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<TResult1 | TResult2> {\n return this.knexQuery.then(onfulfilled as any, onrejected);\n }\n catch<TResult2 = never>(\n onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null\n ): Promise<Expand<TResult> | TResult2> {\n return this.knexQuery.catch(onrejected);\n }\n finally(onfinally?: (() => void) | null): Promise<Expand<TResult>> {\n return this.knexQuery.finally(onfinally);\n }\n\n // 하나만 쿼리\n async first(): Promise<Expand<TResult> | undefined> {\n return this.knexQuery.first();\n }\n // 하나만 쿼리 실패 시 에러\n async firstOrFail(): Promise<TResult> {\n const result = await this.knexQuery.first();\n if (!result) {\n throw new Error(\"No results found\");\n }\n return result;\n }\n\n // 쿼리 후 인덱스 리턴\n async at(index: number): Promise<Expand<TResult> | undefined> {\n const results = (await this) as any[];\n return results[index];\n }\n // 쿼리 후 인덱스 리턴 실패 시 에러\n async assertAt(index: number): Promise<Expand<TResult>> {\n const results = (await this) as any[];\n const result = results[index];\n if (result === undefined) {\n throw new Error(`No result found at index ${index}`);\n }\n return result;\n }\n\n // 쿼리한 레코드에서 특정 컬럼만 추출한 배열 리턴\n async pluck<TColumn extends ResultAvailableColumns<TTables, TResult>>(\n column: TColumn\n ): Promise<ExtractColumnType<TTables, TColumn & string>[]> {\n return this.knexQuery.pluck(column) as Promise<\n ExtractColumnType<TTables, TColumn & string>[]\n >;\n }\n\n // INSERT\n insert(\n data: InsertData<SingleTableValue<TTables>>\n ): Puri<TSchema, {}, number, number[]> {\n this.knexQuery.insert(data);\n return this as any;\n }\n\n // UPDATE\n update(data: WhereCondition<TTables>): Puri<TSchema, {}, number, number> {\n this.knexQuery.update(data);\n return this as any;\n }\n\n // Increment\n increment<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n value: number\n ): this {\n if (value <= 0) {\n throw new Error(\"Increment value must be greater than 0\");\n }\n this.knexQuery.increment(column, value);\n return this;\n }\n // Decrement\n decrement<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n value: number\n ): this {\n if (value <= 0) {\n throw new Error(\"Decrement value must be greater than 0\");\n }\n this.knexQuery.decrement(column, value);\n return this;\n }\n\n // DELETE\n delete(): Puri<TSchema, {}, number, number> {\n this.knexQuery.delete();\n return this as any;\n }\n\n // 확인 쿼리 리턴\n toQuery(): string {\n return this.knexQuery.toQuery();\n }\n\n // 쿼리 디버깅 로그 출력\n debug(): this {\n console.log(\n `${chalk.cyan(\"[Puri Debug]\")} ${chalk.yellow(this.toQuery())}`\n );\n return this;\n }\n\n formatSQL(unformatted: string): string {\n // SQL 예약어 목록\n const keywords = [\n \"SELECT\",\n \"FROM\",\n \"WHERE\",\n \"INSERT\",\n \"INTO\",\n \"VALUES\",\n \"UPDATE\",\n \"DELETE\",\n \"CREATE\",\n \"TABLE\",\n \"ALTER\",\n \"DROP\",\n \"JOIN\",\n \"ON\",\n \"INNER\",\n \"LEFT\",\n \"RIGHT\",\n \"FULL\",\n \"OUTER\",\n \"GROUP\",\n \"BY\",\n \"ORDER\",\n \"HAVING\",\n \"DISTINCT\",\n \"LIMIT\",\n \"OFFSET\",\n \"AS\",\n \"AND\",\n \"OR\",\n \"NOT\",\n \"IN\",\n \"LIKE\",\n \"IS\",\n \"NULL\",\n \"CASE\",\n \"WHEN\",\n \"THEN\",\n \"ELSE\",\n \"END\",\n \"UNION\",\n \"ALL\",\n \"EXISTS\",\n \"BETWEEN\",\n ];\n\n let formatted = unformatted;\n\n // 예약어를 대문자로 변환\n keywords.forEach((keyword) => {\n const regex = new RegExp(`\\\\b${keyword}\\\\b`, \"gi\");\n formatted = formatted.replace(regex, keyword.toUpperCase());\n });\n\n // 주요 절 앞에 줄바꿈 추가\n const majorClauses = [\n \"SELECT\",\n \"FROM\",\n \"WHERE\",\n \"GROUP BY\",\n \"ORDER BY\",\n \"HAVING\",\n \"LIMIT\",\n \"UNION\",\n ];\n majorClauses.forEach((clause) => {\n const regex = new RegExp(`\\\\s+(${clause})\\\\s+`, \"gi\");\n formatted = formatted.replace(regex, `\\n${clause.toUpperCase()} `);\n });\n\n // JOIN 절 처리\n formatted = formatted.replace(\n /\\s+((?:INNER|LEFT|RIGHT|FULL OUTER)\\s+)?JOIN\\s+/gi,\n \"\\n$1JOIN \"\n );\n\n // AND, OR 조건 처리\n formatted = formatted.replace(/\\s+(AND|OR)\\s+/gi, \"\\n $1 \");\n\n // 괄호 처리 및 들여쓰기\n const lines = formatted.split(\"\\n\");\n const indentedLines = [];\n let indentLevel = 0;\n\n for (let line of lines) {\n const trimmedLine = line.trim();\n if (!trimmedLine) continue;\n\n // 닫는 괄호가 있으면 들여쓰기 레벨 감소\n const closingParens = (trimmedLine.match(/\\)/g) || []).length;\n const openingParens = (trimmedLine.match(/\\(/g) || []).length;\n\n if (closingParens > 0 && openingParens === 0) {\n indentLevel = Math.max(0, indentLevel - closingParens);\n }\n\n // 현재 들여쓰기 적용\n const indent = \" \".repeat(indentLevel);\n indentedLines.push(indent + trimmedLine);\n\n // 여는 괄호가 있으면 들여쓰기 레벨 증가\n if (openingParens > closingParens) {\n indentLevel += openingParens - closingParens;\n }\n }\n\n return indentedLines.join(\"\\n\").trim();\n }\n\n // Knex 쿼리 빌더 직접 접근\n raw(): Knex.QueryBuilder {\n return this.knexQuery;\n }\n}\n\nexport class WhereGroup<TTables extends Record<string, any>> {\n constructor(private builder: Knex.QueryBuilder) {}\n\n // where 메서드들\n where(conditions: WhereCondition<TTables>): this;\n where<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n where<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n operator: ComparisonOperator,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n where(...args: any[]): WhereGroup<TTables> {\n this.builder.where(args[0], ...args.slice(1));\n return this;\n }\n\n // orWhere 메서드들\n orWhere(conditions: WhereCondition<TTables>): this;\n orWhere<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n orWhere<TColumn extends AvailableColumns<TTables>>(\n column: TColumn,\n operator: ComparisonOperator,\n value: ExtractColumnType<TTables, TColumn & string>\n ): this;\n orWhere(...args: any[]): WhereGroup<TTables> {\n this.builder.orWhere(args[0], ...args.slice(1));\n return this;\n }\n\n // 중첩 그룹\n whereGroup(callback: (g: WhereGroup<TTables>) => void): this;\n whereGroup(callback: (g: WhereGroup<TTables>) => void): WhereGroup<TTables> {\n this.builder.where((subBuilder) => {\n const subGroup = new WhereGroup<TTables>(subBuilder);\n callback(subGroup);\n });\n return this;\n }\n orWhereGroup(callback: (g: WhereGroup<TTables>) => void): this;\n orWhereGroup(\n callback: (g: WhereGroup<TTables>) => void\n ): WhereGroup<TTables> {\n this.builder.orWhere((subBuilder) => {\n const subGroup = new WhereGroup<TTables>(subBuilder);\n callback(subGroup);\n });\n return this;\n }\n}\n\nexport class JoinClauseGroup<\n TLeft extends Record<string, any>,\n TRight extends Record<string, any>,\n> {\n constructor(private callback: Knex.JoinClause) {}\n\n // ON(AND): 컬럼 = 컬럼\n on(left: AvailableColumns<TLeft>, right: AvailableColumns<TRight>): this;\n // ON(AND): 컬럼 (연산자) 컬럼\n on(\n left: AvailableColumns<TLeft>,\n operator: ComparisonOperator,\n right: AvailableColumns<TRight>\n ): this;\n // ON(AND): 콜백\n on(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;\n // ON(AND) 구현\n on(...args: any[]): this {\n this.callback.on(...(args as [string, string]));\n return this;\n }\n\n // ON(OR): 컬럼 = 컬럼\n orOn(left: AvailableColumns<TLeft>, right: AvailableColumns<TRight>): this;\n // ON(OR): 컬럼 (연산자) 컬럼\n orOn(\n left: AvailableColumns<TLeft>,\n operator: ComparisonOperator,\n right: AvailableColumns<TRight>\n ): this;\n // ON(OR): 콜백\n orOn(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;\n // ON(OR) 구현\n orOn(...args: any[]): this {\n this.callback.orOn(...(args as [string, string]));\n return this;\n }\n}\n"],"names":["JoinClauseGroup","Puri","WhereGroup","knex","tableNameOrSpec","knexQuery","from","entries","Object","length","Error","assert","alias","spec","subqueryBuilder","raw","as","select","selectObj","selectClauses","columnOrFunction","_type","push","_sql","columnPath","selectAll","join","args","__commonJoin","leftJoin","joinType","tableName","callback","joinClause","left","right","where","columnOrConditions","operatorOrValue","value","arguments","whereNull","whereNotNull","whereIn","column","values","whereNotIn","whereMatch","whereRaw","String","whereGroup","builder","group","orWhereGroup","orWhere","orderBy","direction","limit","count","offset","groupBy","columns","having","conditions","then","onfulfilled","onrejected","catch","finally","onfinally","first","firstOrFail","result","at","index","results","assertAt","undefined","pluck","insert","data","update","increment","decrement","delete","toQuery","debug","console","log","chalk","cyan","yellow","formatSQL","unformatted","keywords","formatted","forEach","keyword","regex","RegExp","replace","toUpperCase","majorClauses","clause","lines","split","indentedLines","indentLevel","line","trimmedLine","trim","closingParens","match","openingParens","Math","max","indent","repeat","_return","sum","avg","min","concat","upper","lower","rawString","sql","rawNumber","rawBoolean","rawDate","slice","subBuilder","subGroup","on","orOn"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/database/puri.types.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/database/transaction-context.ts"],"sourcesContent":["import type { PuriTransactionWrapper } from \"./puri-wrapper\";\nimport type { DBPreset } from \"./db\";\n\nexport class TransactionContext {\n private transactions: Map<DBPreset, PuriTransactionWrapper> = new Map();\n\n getTransaction(preset: DBPreset): PuriTransactionWrapper | undefined {\n return this.transactions.get(preset);\n }\n\n setTransaction(preset: DBPreset, trx: PuriTransactionWrapper): void {\n this.transactions.set(preset, trx);\n }\n\n deleteTransaction(preset: DBPreset): void {\n this.transactions.delete(preset);\n }\n}\n"],"names":["TransactionContext","transactions","Map","getTransaction","preset","get","setTransaction","trx","set","deleteTransaction","delete"],"mappings":"oGAGaA,4DAAAA,i0BAAN,IAAA,AAAMA,gCAAN,iCAAMA,4CAAAA,oBACX,sBAAQC,eAAsD,IAAIC,mBADvDF,qBAGXG,IAAAA,uBAAAA,SAAAA,eAAeC,MAAgB,EAC7B,OAAO,IAAI,CAACH,YAAY,CAACI,GAAG,CAACD,OAC/B,IAEAE,IAAAA,uBAAAA,SAAAA,eAAeF,MAAgB,CAAEG,GAA2B,EAC1D,IAAI,CAACN,YAAY,CAACO,GAAG,CAACJ,OAAQG,IAChC,IAEAE,IAAAA,0BAAAA,SAAAA,kBAAkBL,MAAgB,EAChC,IAAI,CAACH,YAAY,CAACS,MAAM,CAACN,OAC3B,YAbWJ"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/database/upsert-builder.ts"],"sourcesContent":["import { randomUUID } from \"crypto\";\nimport _ from \"lodash\";\nimport { Knex } from \"knex\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport { nonNullable } from \"../utils/utils\";\nimport { RowWithId, batchUpdate } from \"./_batch_update\";\n\ntype TableData = {\n references: Set<string>;\n rows: any[];\n uniqueIndexes: { name?: string; columns: string[] }[];\n uniquesMap: Map<string, string>;\n};\nexport type UBRef = {\n uuid: string;\n of: string;\n use?: string;\n};\nexport function isRefField(field: any): field is UBRef {\n return (\n field !== undefined &&\n field !== null &&\n field.of !== undefined &&\n field.uuid !== undefined\n );\n}\n\nexport class UpsertBuilder {\n tables: Map<string, TableData>;\n constructor() {\n this.tables = new Map();\n }\n\n getTable(tableName: string): TableData {\n const table = this.tables.get(tableName);\n if (table === undefined) {\n const tableSpec = (() => {\n try {\n return EntityManager.getTableSpec(tableName);\n } catch {\n return null;\n }\n })();\n\n this.tables.set(tableName, {\n references: new Set(),\n rows: [],\n uniqueIndexes: tableSpec?.uniqueIndexes ?? [],\n uniquesMap: new Map<string, string>(),\n });\n }\n\n return this.tables.get(tableName)!;\n }\n\n hasTable(tableName: string): boolean {\n return this.tables.has(tableName);\n }\n\n register<T extends string>(\n tableName: string,\n row: {\n [key in T]?:\n | UBRef\n | string\n | number\n | boolean\n | bigint\n | null\n | object\n | unknown;\n }\n ): UBRef {\n const table = this.getTable(tableName);\n\n // 해당 테이블의 unique 인덱스를 순회하며 키 생성\n const uniqueKeys = table.uniqueIndexes\n .map((unqIndex) => {\n const uniqueKeyArray = unqIndex.columns.map((unqCol) => {\n const val = row[unqCol as keyof typeof row];\n if (isRefField(val)) {\n return val.uuid;\n } else {\n return row[unqCol as keyof typeof row] ?? randomUUID(); // nullable인 경우 uuid로 랜덤값 삽입\n }\n });\n\n // 값이 모두 null인 경우 키 생성 패스\n if (uniqueKeyArray.length === 0) {\n return null;\n }\n return uniqueKeyArray.join(\"---delimiter--\");\n })\n .filter(nonNullable);\n\n // uuid 생성 로직\n const uuid: string = (() => {\n // 키를 순회하여 이미 존재하는 키가 있는지 확인\n if (uniqueKeys.length > 0) {\n for (const uniqueKey of uniqueKeys) {\n if (table.uniquesMap.has(uniqueKey)) {\n return table.uniquesMap.get(uniqueKey)!; // 이미 has 체크를 했으므로 undefined 불가능\n }\n }\n }\n\n // 찾을 수 없는 경우 생성\n return randomUUID();\n })();\n\n // 모든 유니크키에 대해 유니크맵에 uuid 저장\n if (uniqueKeys.length > 0) {\n for (const uniqueKey of uniqueKeys) {\n table.uniquesMap.set(uniqueKey, uuid);\n }\n }\n\n // 이 테이블에 사용된 RefField를 순회하여, 현재 테이블 정보에 어떤 필드를 참조하는지 추가\n // 이 정보를 나중에 치환할 때 사용\n row = Object.keys(row).reduce((r, rowKey) => {\n const rowValue = row[rowKey as keyof typeof row];\n\n if (isRefField(rowValue)) {\n rowValue.use ??= \"id\";\n table.references.add(rowValue.of + \".\" + rowValue.use);\n r[rowKey] = rowValue;\n } else if (typeof rowValue === \"object\" && !(rowValue instanceof Date)) {\n // object인 경우 JSON으로 변환\n r[rowKey] = rowValue === null ? null : JSON.stringify(rowValue);\n } else {\n r[rowKey] = rowValue;\n }\n return r;\n }, {} as any);\n\n table.rows.push({\n uuid,\n ...row,\n });\n\n return {\n of: tableName,\n uuid: (row as { uuid?: string }).uuid ?? uuid,\n };\n }\n\n async upsert(\n wdb: Knex,\n tableName: string,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertOrInsert(wdb, tableName, \"upsert\", chunkSize);\n }\n async insertOnly(\n wdb: Knex,\n tableName: string,\n chunkSize?: number\n ): Promise<number[]> {\n return this.upsertOrInsert(wdb, tableName, \"insert\", chunkSize);\n }\n\n async upsertOrInsert(\n wdb: Knex,\n tableName: string,\n mode: \"upsert\" | \"insert\",\n chunkSize?: number\n ): Promise<number[]> {\n if (this.hasTable(tableName) === false) {\n return [];\n }\n\n const table = this.tables.get(tableName);\n if (table === undefined) {\n throw new Error(`존재하지 않는 테이블 ${tableName}에 upsert 요청`);\n } else if (table.rows.length === 0) {\n throw new Error(`${tableName}에 upsert 할 데이터가 없습니다.`);\n }\n\n if (\n table.rows.some((row) =>\n Object.entries(row).some(\n ([, value]) => isRefField(value) && value.of !== tableName\n )\n )\n ) {\n throw new Error(`${tableName} 해결되지 않은 참조가 있습니다.`);\n }\n\n // 전체 테이블 순회하여 현재 테이블 참조하는 모든 테이블 추출\n const { references, refTables } = Array.from(this.tables).reduce(\n (r, [, table]) => {\n const reference = Array.from(table.references.values()).find((ref) =>\n ref.includes(tableName + \".\")\n );\n if (reference) {\n r.references.push(reference);\n r.refTables.push(table);\n }\n\n return r;\n },\n {\n references: [] as string[],\n refTables: [] as TableData[],\n }\n );\n const extractFields = _.uniq(references).map(\n (reference) => reference.split(\".\")[1]\n );\n\n // 내부 참조 있는 경우 필터하여 분리\n const groups = _.groupBy(table.rows, (row) =>\n Object.entries(row).some(([, value]) => isRefField(value))\n ? \"selfRef\"\n : \"normal\"\n );\n const normalRows = groups.normal ?? [];\n const selfRefRows = groups.selfRef ?? [];\n\n const chunks = chunkSize ? _.chunk(normalRows, chunkSize) : [normalRows];\n const uuidMap = new Map<string, any>();\n\n for (const chunk of chunks) {\n const q = wdb.insert(chunk).into(tableName);\n if (mode === \"insert\") {\n await q;\n } else if (mode === \"upsert\") {\n await q.onDuplicateUpdate.apply(q, Object.keys(normalRows[0]));\n }\n\n // upsert된 row들을 다시 조회하여 uuidMap에 저장\n const uuids = chunk.map((row) => row.uuid);\n const upsertedRows = await wdb(tableName)\n .select(_.uniq([\"uuid\", \"id\", ...extractFields]))\n .whereIn(\"uuid\", uuids);\n upsertedRows.forEach((row: any) => {\n uuidMap.set(row.uuid, row);\n });\n }\n\n // 해당 테이블 참조를 실제 밸류로 변경\n refTables.map((table) => {\n table.rows = table.rows.map((row) => {\n Object.keys(row).map((key) => {\n const prop = row[key];\n if (isRefField(prop) && prop.of === tableName) {\n const parent = uuidMap.get(prop.uuid);\n if (parent === undefined) {\n console.error(prop);\n throw new Error(\n `존재하지 않는 uuid ${prop.uuid} -- in ${tableName}`\n );\n }\n row[key] = parent[prop.use ?? \"id\"];\n }\n });\n return row;\n });\n });\n\n const allIds = Array.from(uuidMap.values()).map((row) => row.id);\n\n // 자기 참조가 있는 경우 재귀적으로 upsert\n if (selfRefRows.length > 0) {\n // 처리된 데이터를 제외하고 다시 upsert\n table.rows = selfRefRows;\n const selfRefIds = await this.upsert(wdb, tableName, chunkSize);\n allIds.push(...selfRefIds);\n } else {\n // 자기 참조가 없으면 해당 테이블의 데이터 초기화\n table.rows = [];\n table.references.clear();\n table.uniquesMap.clear();\n }\n\n return allIds;\n }\n\n async updateBatch(\n wdb: Knex,\n tableName: string,\n options?: {\n chunkSize?: number;\n where?: string | string[];\n }\n ): Promise<void> {\n options = _.defaults(options, {\n chunkSize: 500,\n where: \"id\",\n });\n\n if (this.hasTable(tableName) === false) {\n return;\n }\n const table = this.tables.get(tableName)!;\n if (table.rows.length === 0) {\n return;\n }\n\n const whereColumns = Array.isArray(options.where)\n ? options.where\n : [options.where ?? \"id\"];\n const rows = table.rows.map((_row) => {\n const { uuid, ...row } = _row;\n return row as RowWithId<string>;\n });\n\n await batchUpdate(wdb, tableName, whereColumns, rows, options.chunkSize);\n\n // updateBatch 완료 후 처리된 데이터 제거\n table.rows = [];\n table.references.clear();\n table.uniquesMap.clear();\n }\n}\n"],"names":["UpsertBuilder","isRefField","field","undefined","of","uuid","tables","Map","getTable","tableName","table","get","tableSpec","EntityManager","getTableSpec","set","references","Set","rows","uniqueIndexes","uniquesMap","hasTable","has","register","row","uniqueKeys","map","unqIndex","uniqueKeyArray","columns","unqCol","val","randomUUID","length","join","filter","nonNullable","uniqueKey","Object","keys","reduce","r","rowKey","rowValue","use","add","Date","JSON","stringify","push","upsert","wdb","chunkSize","upsertOrInsert","insertOnly","mode","Array","refTables","extractFields","groups","normalRows","selfRefRows","chunks","uuidMap","chunk","q","uuids","upsertedRows","allIds","selfRefIds","Error","some","entries","value","from","reference","values","find","ref","includes","_","uniq","split","groupBy","normal","selfRef","insert","into","onDuplicateUpdate","apply","select","whereIn","forEach","key","prop","parent","console","error","id","clear","updateBatch","options","whereColumns","defaults","where","isArray","_row","batchUpdate"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/entity/entity-manager.ts"],"sourcesContent":["import chalk from \"chalk\";\nimport { glob } from \"fs/promises\";\nimport inflection from \"inflection\";\nimport _ from \"lodash\";\nimport path from \"path\";\nimport { Entity } from \"./entity\";\nimport { EntityJson } from \"../types/types\";\nimport { Sonamu } from \"../api/sonamu\";\nimport { readFile } from \"fs/promises\";\n\nexport type EntityNamesRecord = Record<\n | \"fs\"\n | \"fsPlural\"\n | \"camel\"\n | \"camelPlural\"\n | \"capital\"\n | \"capitalPlural\"\n | \"upper\"\n | \"constant\",\n string\n>;\ntype TableSpec = {\n name: string;\n uniqueIndexes: { name?: string; columns: string[] }[];\n};\nclass EntityManagerClass {\n private entities: Map<string, Entity> = new Map();\n public modulePaths: Map<string, string> = new Map();\n private tableSpecs: Map<string, TableSpec> = new Map();\n public isAutoloaded: boolean = false;\n\n // 경로 전달받아 모든 entity.json 파일 로드\n async autoload(doSilent: boolean = false) {\n if (this.isAutoloaded) {\n return;\n }\n const pathPattern = path.join(\n Sonamu.apiRootPath,\n \"/src/application/**/*.entity.json\"\n );\n !doSilent && console.log(chalk.yellow(`autoload ${pathPattern}`));\n\n for await (const file of glob(path.resolve(pathPattern!))) {\n await this.register(JSON.parse((await readFile(file)).toString()));\n }\n this.isAutoloaded = true;\n }\n\n async reload(doSilent: boolean = false) {\n console.log(\"reload\");\n this.entities.clear();\n this.modulePaths.clear();\n this.tableSpecs.clear();\n this.isAutoloaded = false;\n\n const sonamuPath = path.join(\n Sonamu.apiRootPath,\n `dist/application/sonamu.generated.js`\n );\n // CJS\n if (require?.cache && require.cache[sonamuPath]) {\n delete require.cache[sonamuPath];\n }\n\n return await this.autoload(doSilent);\n }\n\n async register(json: EntityJson): Promise<void> {\n const entity = new Entity(json);\n await entity.registerModulePaths();\n entity.registerTableSpecs();\n this.entities.set(json.id, entity);\n // console.debug(chalk.cyan(`register :: ${entity.id}`));\n }\n\n get(entityId: string): Entity {\n const entity = this.entities.get(entityId);\n if (entity === undefined) {\n throw new Error(`존재하지 않는 Entity 요청 ${entityId}`);\n }\n\n return entity;\n }\n\n exists(entityId: string): boolean {\n const entity = this.entities.get(entityId);\n return entity !== undefined;\n }\n\n getAllIds(): string[] {\n return Array.from(EntityManager.entities.keys()).sort();\n }\n\n getAllParentIds(): string[] {\n return this.getAllIds().filter((entityId) => {\n const entity = this.get(entityId);\n return entity.parentId === undefined;\n });\n }\n\n getChildrenIds(parentId: string): string[] {\n return this.getAllIds().filter((entityId) => {\n const entity = this.get(entityId);\n return entity.parentId === parentId;\n });\n }\n\n setModulePath(key: string, modulePath: string): void {\n // console.debug(chalk.cyan(`setModulePath :: ${key} :: ${modulePath}`));\n this.modulePaths.set(key, modulePath);\n }\n\n getModulePath(key: string): string {\n const modulePath = this.modulePaths.get(key);\n if (modulePath === undefined) {\n throw new Error(`존재하지 않는 모듈 패스 요청 ${key}`);\n }\n\n return modulePath;\n }\n\n setTableSpec(tableSpec: TableSpec) {\n this.tableSpecs.set(tableSpec.name, tableSpec);\n }\n\n getTableSpec(key: string): TableSpec {\n const tableSpec = this.tableSpecs.get(key);\n if (tableSpec === undefined) {\n throw new Error(`존재하지 않는 테이블 스펙 요청 ${key}`);\n }\n\n return tableSpec;\n }\n\n getNamesFromId(entityId: string): EntityNamesRecord {\n // entityId가 단복수 동형 단어인 경우 List 붙여서 생성\n const pluralized =\n inflection.pluralize(entityId) === entityId\n ? `${entityId}List`\n : inflection.pluralize(entityId);\n\n return {\n fs: inflection.dasherize(inflection.underscore(entityId)).toLowerCase(),\n fsPlural: inflection\n .dasherize(inflection.underscore(pluralized))\n .toLowerCase(),\n camel: inflection.camelize(entityId, true),\n camelPlural: inflection.camelize(pluralized, true),\n capital: entityId,\n capitalPlural: pluralized,\n upper: entityId.toUpperCase(),\n constant: inflection.underscore(entityId).toUpperCase(),\n };\n }\n}\n\nexport const EntityManager = new EntityManagerClass();\n"],"names":["EntityManager","EntityManagerClass","entities","Map","modulePaths","tableSpecs","isAutoloaded","autoload","doSilent","pathPattern","file","path","join","Sonamu","apiRootPath","console","log","chalk","yellow","glob","resolve","register","JSON","parse","readFile","toString","reload","require","sonamuPath","clear","cache","json","entity","Entity","registerModulePaths","registerTableSpecs","set","id","get","entityId","undefined","Error","exists","getAllIds","Array","from","keys","sort","getAllParentIds","filter","parentId","getChildrenIds","setModulePath","key","modulePath","getModulePath","setTableSpec","tableSpec","name","getTableSpec","getNamesFromId","pluralized","inflection","pluralize","fs","dasherize","underscore","toLowerCase","fsPlural","camel","camelize","camelPlural","capital","capitalPlural","upper","toUpperCase","constant"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/entity/entity-utils.ts"],"sourcesContent":["import inflection from \"inflection\";\nimport {\n BelongsToOneRelationProp,\n BigIntegerProp,\n BooleanProp,\n DateProp,\n DateTimeProp,\n DecimalProp,\n DistributiveOmit,\n DoubleProp,\n EnumProp,\n FloatProp,\n HasManyRelationProp,\n IntegerProp,\n JsonProp,\n ManyToManyRelationProp,\n OneToOneRelationProp,\n EntityIndex,\n StringProp,\n TextProp,\n TimeProp,\n TimestampProp,\n UuidProp,\n VirtualProp,\n} from \"../types/types\";\nimport { asArray } from \"../utils/model\";\n\nexport const p = {\n integer,\n bigInteger,\n text,\n string,\n float,\n double,\n decimal,\n boolean,\n date,\n dateTime,\n time,\n timestamp,\n json,\n uuid,\n enums,\n virtual,\n relationOneToOne,\n relationBelongsToOne,\n relationHasMany,\n relationManyToMany,\n};\n\nfunction integer(\n name: string,\n option?: Omit<IntegerProp, \"name\" | \"type\">\n): IntegerProp {\n return {\n name,\n type: \"integer\",\n ...option,\n };\n}\nfunction bigInteger(\n name: string,\n option?: Omit<BigIntegerProp, \"name\" | \"type\">\n): BigIntegerProp {\n return {\n name,\n type: \"bigInteger\",\n ...option,\n };\n}\nfunction text(name: string, option: Omit<TextProp, \"name\" | \"type\">): TextProp {\n return {\n name,\n type: \"text\",\n ...option,\n };\n}\nfunction string(\n name: string,\n option: Omit<StringProp, \"name\" | \"type\">\n): StringProp {\n return {\n name,\n type: \"string\",\n ...option,\n };\n}\nfunction float(\n name: string,\n option?: Omit<FloatProp, \"name\" | \"type\">\n): FloatProp {\n return {\n name,\n type: \"float\",\n precision: 8,\n scale: 2,\n ...option,\n };\n}\nfunction double(\n name: string,\n option?: Omit<DoubleProp, \"name\" | \"type\">\n): DoubleProp {\n return {\n name,\n type: \"double\",\n precision: 8,\n scale: 2,\n ...option,\n };\n}\nfunction decimal(\n name: string,\n option?: Omit<DecimalProp, \"name\" | \"type\">\n): DecimalProp {\n return {\n name,\n type: \"decimal\",\n precision: 8,\n scale: 2,\n ...option,\n };\n}\nfunction boolean(\n name: string,\n option?: Omit<BooleanProp, \"name\" | \"type\">\n): BooleanProp {\n return {\n name,\n type: \"boolean\",\n ...option,\n };\n}\nfunction date(\n name: string,\n option?: Omit<DateProp, \"name\" | \"type\"> & { now?: true }\n): DateProp {\n if (option?.now === true) {\n delete option.now;\n option.dbDefault = \"CURRENT_TIMESTAMP\";\n }\n return {\n name,\n type: \"date\",\n ...option,\n };\n}\nfunction dateTime(\n name: string,\n option?: Omit<DateTimeProp, \"name\" | \"type\"> & { now?: true }\n): DateTimeProp {\n if (option?.now === true) {\n delete option.now;\n option.dbDefault = \"CURRENT_TIMESTAMP\";\n }\n return {\n name,\n type: \"datetime\",\n ...option,\n };\n}\nfunction time(\n name: string,\n option?: Omit<TimeProp, \"name\" | \"type\"> & { now?: true }\n): TimeProp {\n if (option?.now === true) {\n delete option.now;\n option.dbDefault = \"CURRENT_TIMESTAMP\";\n }\n return {\n name,\n type: \"time\",\n ...option,\n };\n}\nfunction timestamp(\n name: string,\n option?: Omit<TimestampProp, \"name\" | \"type\"> & { now?: true }\n): TimestampProp {\n if (option?.now === true) {\n delete option.now;\n option.dbDefault = \"CURRENT_TIMESTAMP\";\n }\n return {\n name,\n type: \"timestamp\",\n ...option,\n };\n}\nfunction json(name: string, option: Omit<JsonProp, \"name\" | \"type\">): JsonProp {\n return {\n name,\n type: \"json\",\n ...option,\n };\n}\nfunction uuid(name: string, option: Omit<UuidProp, \"name\" | \"type\">): UuidProp {\n return {\n name,\n type: \"uuid\",\n ...option,\n };\n}\nfunction enums(\n name: string,\n option: Omit<EnumProp, \"name\" | \"type\" | \"id\"> & { id?: string }\n): EnumProp {\n return {\n name,\n type: \"enum\",\n id: option.id ?? `$Model${inflection.camelize(name)}`,\n ...option,\n };\n}\nfunction virtual(\n name: string,\n option: Omit<VirtualProp, \"name\" | \"type\" | \"dbDefault\" | \"toFilter\">\n): VirtualProp {\n return {\n name,\n type: \"virtual\",\n ...option,\n };\n}\nfunction relationOneToOne(\n name: string,\n option: DistributiveOmit<\n OneToOneRelationProp,\n \"name\" | \"type\" | \"relationType\"\n >\n): OneToOneRelationProp {\n return {\n name,\n type: \"relation\",\n relationType: \"OneToOne\",\n ...option,\n };\n}\nfunction relationBelongsToOne(\n name: string,\n option: Omit<BelongsToOneRelationProp, \"name\" | \"type\" | \"relationType\">\n): BelongsToOneRelationProp {\n option.useConstraint = (option.useConstraint ?? true) as false;\n return {\n name,\n type: \"relation\",\n relationType: \"BelongsToOne\",\n ...option,\n };\n}\nfunction relationHasMany(\n name: string,\n option: Omit<HasManyRelationProp, \"name\" | \"type\" | \"relationType\">\n): HasManyRelationProp {\n return {\n name,\n type: \"relation\",\n relationType: \"HasMany\",\n ...option,\n };\n}\nfunction relationManyToMany(\n name: string,\n option: Omit<ManyToManyRelationProp, \"name\" | \"type\" | \"relationType\">\n): ManyToManyRelationProp {\n return {\n name,\n type: \"relation\",\n relationType: \"ManyToMany\",\n ...option,\n };\n}\n\nexport const i = {\n index,\n unique,\n};\n\nfunction index(columns: string | string[]): EntityIndex {\n return {\n type: \"index\",\n columns: asArray(columns),\n };\n}\n\nfunction unique(columns: string | string[]): EntityIndex {\n return {\n type: \"unique\",\n columns: asArray(columns),\n };\n}\n"],"names":["i","p","integer","bigInteger","text","string","float","double","decimal","boolean","date","dateTime","time","timestamp","json","uuid","enums","virtual","relationOneToOne","relationBelongsToOne","relationHasMany","relationManyToMany","name","option","type","precision","scale","now","dbDefault","id","inflection","camelize","relationType","useConstraint","index","unique","columns","asArray"],"mappings":"mPAiRaA,WAAAA,OAtPAC,WAAAA,mEA3BU,kCAyBC,0sBAEjB,IAAMA,EAAI,CACfC,QAAAA,QACAC,WAAAA,WACAC,KAAAA,KACAC,OAAAA,OACAC,MAAAA,MACAC,OAAAA,OACAC,QAAAA,QACAC,QAAAA,QACAC,KAAAA,KACAC,SAAAA,SACAC,KAAAA,KACAC,UAAAA,UACAC,KAAAA,KACAC,KAAAA,KACAC,MAAAA,MACAC,QAAAA,QACAC,iBAAAA,iBACAC,qBAAAA,qBACAC,gBAAAA,gBACAC,mBAAAA,kBACF,EAEA,SAASnB,QACPoB,IAAY,CACZC,MAA2C,EAE3C,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACHD,OAEP,CACA,SAASpB,WACPmB,IAAY,CACZC,MAA8C,EAE9C,OAAO,gBACLD,KAAAA,KACAE,KAAM,cACHD,OAEP,CACA,SAASnB,KAAKkB,IAAY,CAAEC,MAAuC,EACjE,OAAO,gBACLD,KAAAA,KACAE,KAAM,QACHD,OAEP,CACA,SAASlB,OACPiB,IAAY,CACZC,MAAyC,EAEzC,OAAO,gBACLD,KAAAA,KACAE,KAAM,UACHD,OAEP,CACA,SAASjB,MACPgB,IAAY,CACZC,MAAyC,EAEzC,OAAO,gBACLD,KAAAA,KACAE,KAAM,QACNC,UAAW,EACXC,MAAO,GACJH,OAEP,CACA,SAAShB,OACPe,IAAY,CACZC,MAA0C,EAE1C,OAAO,gBACLD,KAAAA,KACAE,KAAM,SACNC,UAAW,EACXC,MAAO,GACJH,OAEP,CACA,SAASf,QACPc,IAAY,CACZC,MAA2C,EAE3C,OAAO,gBACLD,KAAAA,KACAE,KAAM,UACNC,UAAW,EACXC,MAAO,GACJH,OAEP,CACA,SAASd,QACPa,IAAY,CACZC,MAA2C,EAE3C,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACHD,OAEP,CACA,SAASb,KACPY,IAAY,CACZC,MAAyD,EAEzD,GAAIA,CAAAA,eAAAA,uBAAAA,OAAQI,GAAG,IAAK,KAAM,CACxB,OAAOJ,OAAOI,GAAG,AACjBJ,CAAAA,OAAOK,SAAS,CAAG,mBACrB,CACA,OAAO,gBACLN,KAAAA,KACAE,KAAM,QACHD,OAEP,CACA,SAASZ,SACPW,IAAY,CACZC,MAA6D,EAE7D,GAAIA,CAAAA,eAAAA,uBAAAA,OAAQI,GAAG,IAAK,KAAM,CACxB,OAAOJ,OAAOI,GAAG,AACjBJ,CAAAA,OAAOK,SAAS,CAAG,mBACrB,CACA,OAAO,gBACLN,KAAAA,KACAE,KAAM,YACHD,OAEP,CACA,SAASX,KACPU,IAAY,CACZC,MAAyD,EAEzD,GAAIA,CAAAA,eAAAA,uBAAAA,OAAQI,GAAG,IAAK,KAAM,CACxB,OAAOJ,OAAOI,GAAG,AACjBJ,CAAAA,OAAOK,SAAS,CAAG,mBACrB,CACA,OAAO,gBACLN,KAAAA,KACAE,KAAM,QACHD,OAEP,CACA,SAASV,UACPS,IAAY,CACZC,MAA8D,EAE9D,GAAIA,CAAAA,eAAAA,uBAAAA,OAAQI,GAAG,IAAK,KAAM,CACxB,OAAOJ,OAAOI,GAAG,AACjBJ,CAAAA,OAAOK,SAAS,CAAG,mBACrB,CACA,OAAO,gBACLN,KAAAA,KACAE,KAAM,aACHD,OAEP,CACA,SAAST,KAAKQ,IAAY,CAAEC,MAAuC,EACjE,OAAO,gBACLD,KAAAA,KACAE,KAAM,QACHD,OAEP,CACA,SAASR,KAAKO,IAAY,CAAEC,MAAuC,EACjE,OAAO,gBACLD,KAAAA,KACAE,KAAM,QACHD,OAEP,CACA,SAASP,MACPM,IAAY,CACZC,MAAgE,MAK1DA,WAHN,OAAO,gBACLD,KAAAA,KACAE,KAAM,OACNK,GAAIN,CAAAA,WAAAA,OAAOM,EAAE,UAATN,oBAAAA,WAAa,AAAC,SAAkC,OAA1BO,mBAAU,CAACC,QAAQ,CAACT,QAC3CC,OAEP,CACA,SAASN,QACPK,IAAY,CACZC,MAAqE,EAErE,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACHD,OAEP,CACA,SAASL,iBACPI,IAAY,CACZC,MAGC,EAED,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACNQ,aAAc,YACXT,OAEP,CACA,SAASJ,qBACPG,IAAY,CACZC,MAAwE,MAEhDA,qBAAxBA,CAAAA,OAAOU,aAAa,CAAIV,CAAAA,sBAAAA,OAAOU,aAAa,UAApBV,+BAAAA,sBAAwB,KAChD,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACNQ,aAAc,gBACXT,OAEP,CACA,SAASH,gBACPE,IAAY,CACZC,MAAmE,EAEnE,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACNQ,aAAc,WACXT,OAEP,CACA,SAASF,mBACPC,IAAY,CACZC,MAAsE,EAEtE,OAAO,gBACLD,KAAAA,KACAE,KAAM,WACNQ,aAAc,cACXT,OAEP,CAEO,IAAMvB,EAAI,CACfkC,MAAAA,MACAC,OAAAA,MACF,EAEA,SAASD,MAAME,OAA0B,EACvC,MAAO,CACLZ,KAAM,QACNY,QAASC,GAAAA,cAAO,EAACD,QACnB,CACF,CAEA,SAASD,OAAOC,OAA0B,EACxC,MAAO,CACLZ,KAAM,SACNY,QAASC,GAAAA,cAAO,EAACD,QACnB,CACF"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/entity/entity.ts"],"sourcesContent":["import _ from \"lodash\";\nimport { EntityManager as EntityManager } from \"./entity-manager\";\nimport {\n EntityProp,\n RelationProp,\n isRelationProp,\n SubsetQuery,\n isVirtualProp,\n isBelongsToOneRelationProp,\n isOneToOneRelationProp,\n isHasManyRelationProp,\n isManyToManyRelationProp,\n EntityPropNode,\n isEnumProp,\n StringProp,\n EntityIndex,\n EntityJson,\n EntitySubsetRow,\n} from \"../types/types\";\nimport inflection from \"inflection\";\nimport path from \"path\";\nimport { writeFile } from \"fs/promises\";\nimport { z } from \"zod\";\nimport { Sonamu } from \"../api/sonamu\";\nimport prettier from \"prettier\";\nimport { nonNullable } from \"../utils/utils\";\nimport { exists } from \"../utils/fs-utils\";\n\nexport class Entity {\n id: string;\n parentId?: string;\n table: string;\n title: string;\n names: {\n parentFs: string;\n fs: string;\n module: string;\n };\n props: EntityProp[];\n propsDict: {\n [key: string]: EntityProp;\n };\n relations: {\n [key: string]: RelationProp;\n };\n indexes: EntityIndex[];\n subsets: {\n [key: string]: string[];\n };\n types: {\n [name: string]: z.ZodTypeAny;\n } = {};\n enums: {\n [enumId: string]: z.ZodEnum<any>;\n } = {};\n enumLabels: {\n [enumId: string]: {\n [key: string]: string;\n };\n } = {};\n\n constructor({\n id,\n parentId,\n table,\n title,\n props,\n indexes,\n subsets,\n enums,\n }: EntityJson) {\n // id\n this.id = id;\n this.parentId = parentId;\n this.title = title ?? this.id;\n this.table = table ?? inflection.underscore(inflection.pluralize(id));\n\n // props\n if (props) {\n this.props = props.map((prop) => {\n if (isEnumProp(prop)) {\n if (prop.id.includes(\"$Model\")) {\n prop.id = prop.id.replace(\"$Model\", id);\n }\n }\n return prop;\n });\n this.propsDict = props.reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n\n // relations\n this.relations = props\n .filter((prop) => isRelationProp(prop))\n .reduce((result, prop) => {\n return {\n ...result,\n [prop.name]: prop,\n };\n }, {});\n } else {\n this.props = [];\n this.propsDict = {};\n this.relations = {};\n }\n\n // indexes\n this.indexes = indexes ?? [];\n\n // subsets\n this.subsets = subsets ?? {};\n\n // enums\n this.enumLabels = enums ?? {};\n this.enums = Object.fromEntries(\n Object.entries(this.enumLabels).map(([key, enumLabel]) => {\n return [\n key,\n z.enum(\n Object.keys(enumLabel) as unknown as readonly [string, ...string[]]\n ),\n ];\n })\n );\n\n // names\n this.names = {\n parentFs: inflection\n .dasherize(inflection.underscore(parentId ?? id))\n .toLowerCase(),\n fs: inflection.dasherize(inflection.underscore(id)).toLowerCase(),\n module: id,\n };\n }\n\n /*\n subset SELECT/JOIN/LOADER 결과 리턴\n */\n getSubsetQuery(subsetKey: string): SubsetQuery {\n const subset = this.subsets[subsetKey];\n\n const result: SubsetQuery = this.resolveSubsetQuery(\"\", subset);\n return result;\n }\n\n /*\n */\n resolveSubsetQuery(\n prefix: string,\n fields: string[],\n isAlreadyOuterJoined: boolean = false\n ): SubsetQuery {\n // prefix 치환 (prefix는 ToOneRelation이 복수로 붙은 경우 모두 __로 변경됨)\n prefix = prefix.replace(/\\./g, \"__\");\n\n // 서브셋을 1뎁스만 분리하여 그룹핑\n const subsetGroup = _.groupBy(fields, (field) => {\n if (field.includes(\".\")) {\n const [rel] = field.split(\".\");\n return rel;\n } else {\n return \"\";\n }\n });\n\n const result = Object.keys(subsetGroup).reduce(\n (r, groupKey) => {\n const fields = subsetGroup[groupKey];\n // 현재 테이블 필드셋은 select, virtual에 추가하고 리턴\n if (groupKey === \"\") {\n const realFields = fields.filter(\n (field) => !isVirtualProp(this.propsDict[field])\n );\n const virtualFields = fields.filter((field) =>\n isVirtualProp(this.propsDict[field])\n );\n\n if (prefix === \"\") {\n // 현재 테이블인 경우\n r.select = r.select.concat(\n realFields.map((field) => `${this.table}.${field}`)\n );\n r.virtual = r.virtual.concat(virtualFields);\n } else {\n // 넘어온 테이블인 경우\n r.select = r.select.concat(\n realFields.map(\n (field) => `${prefix}.${field} as ${prefix}__${field}`\n )\n );\n }\n\n return r;\n }\n\n const relation = this.relations[groupKey];\n if (relation === undefined) {\n throw new Error(`존재하지 않는 relation 참조 ${groupKey}`);\n }\n const relEntity = EntityManager.get(relation.with);\n\n if (\n isOneToOneRelationProp(relation) ||\n isBelongsToOneRelationProp(relation)\n ) {\n // -One Relation: JOIN 으로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n\n // -One Relation에서 id 필드만 참조하는 경우 릴레이션 넘기지 않고 리턴\n if (relFields.length === 1 && relFields[0] === \"id\") {\n if (prefix === \"\") {\n r.select = r.select.concat(`${this.table}.${groupKey}_id`);\n } else {\n r.select = r.select.concat(\n `${prefix}.${groupKey}_id as ${prefix}__${groupKey}_id`\n );\n }\n return r;\n }\n\n // innerOrOuter\n const innerOrOuter = (() => {\n if (isAlreadyOuterJoined) {\n return \"outer\";\n }\n\n if (isOneToOneRelationProp(relation)) {\n if (\n relation.hasJoinColumn === true &&\n (relation.nullable ?? false) === false\n ) {\n return \"inner\";\n } else {\n return \"outer\";\n }\n } else {\n if (relation.nullable) {\n return \"outer\";\n } else {\n return \"inner\";\n }\n }\n })();\n const relSubsetQuery = relEntity.resolveSubsetQuery(\n `${prefix !== \"\" ? prefix + \".\" : \"\"}${groupKey}`,\n relFields,\n innerOrOuter === \"outer\"\n );\n r.select = r.select.concat(relSubsetQuery.select);\n r.virtual = r.virtual.concat(relSubsetQuery.virtual);\n\n const joinAs = prefix === \"\" ? groupKey : prefix + \"__\" + groupKey;\n const fromTable = prefix === \"\" ? this.table : prefix;\n\n let joinClause;\n if (relation.customJoinClause) {\n joinClause = {\n custom: relation.customJoinClause,\n };\n } else {\n let from, to;\n if (isOneToOneRelationProp(relation)) {\n if (relation.hasJoinColumn) {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n } else {\n from = `${fromTable}.id`;\n to = `${joinAs}.${inflection.underscore(\n this.names.fs.replace(/\\-/g, \"_\")\n )}_id`;\n }\n } else {\n from = `${fromTable}.${relation.name}_id`;\n to = `${joinAs}.id`;\n }\n joinClause = {\n from,\n to,\n };\n }\n\n r.joins.push({\n as: joinAs,\n join: innerOrOuter,\n table: relEntity.table,\n ...joinClause,\n });\n\n // BelongsToOne 밑에 HasMany가 붙은 경우\n if (relSubsetQuery.loaders.length > 0) {\n const convertedLoaders = relSubsetQuery.loaders.map((loader) => {\n const newAs = [groupKey, loader.as].join(\"__\");\n return {\n as: newAs,\n table: loader.table,\n manyJoin: loader.manyJoin,\n oneJoins: loader.oneJoins,\n select: loader.select,\n loaders: loader.loaders,\n };\n });\n\n r.loaders = [...r.loaders, ...convertedLoaders];\n }\n\n r.joins = r.joins.concat(relSubsetQuery.joins);\n } else if (\n isHasManyRelationProp(relation) ||\n isManyToManyRelationProp(relation)\n ) {\n // -Many Relation: Loader 로 처리\n const relFields = fields.map((field) =>\n field.split(\".\").slice(1).join(\".\")\n );\n const relSubsetQuery = relEntity.resolveSubsetQuery(\"\", relFields);\n\n let manyJoin: SubsetQuery[\"loaders\"][number][\"manyJoin\"];\n if (isHasManyRelationProp(relation)) {\n const fromCol = relation?.fromColumn ?? \"id\";\n manyJoin = {\n fromTable: this.table,\n fromCol,\n idField: prefix === \"\" ? `${fromCol}` : `${prefix}__${fromCol}`,\n toTable: relEntity.table,\n toCol: relation.joinColumn,\n };\n } else if (isManyToManyRelationProp(relation)) {\n manyJoin = {\n fromTable: this.table,\n fromCol: \"id\",\n idField: prefix === \"\" ? `id` : `${prefix}__id`,\n through: {\n table: relation.joinTable,\n fromCol: `${inflection.singularize(this.table)}_id`,\n toCol: `${inflection.singularize(relEntity.table)}_id`,\n },\n toTable: relEntity.table,\n toCol: \"id\",\n };\n } else {\n throw new Error();\n }\n\n r.loaders.push({\n as: groupKey,\n table: relEntity.table,\n manyJoin,\n oneJoins: relSubsetQuery.joins,\n select: relSubsetQuery.select,\n loaders: relSubsetQuery.loaders,\n });\n }\n\n return r;\n },\n {\n select: [],\n virtual: [],\n joins: [],\n loaders: [],\n } as SubsetQuery\n );\n return result;\n }\n\n /*\n FieldExpr[] 을 EntityPropNode[] 로 변환\n */\n fieldExprsToPropNodes(\n fieldExprs: string[],\n entity: Entity = this\n ): EntityPropNode[] {\n const groups = fieldExprs.reduce(\n (result, fieldExpr) => {\n let key, value, elseExpr;\n if (fieldExpr.includes(\".\")) {\n [key, ...elseExpr] = fieldExpr.split(\".\");\n value = elseExpr.join(\".\");\n } else {\n key = \"\";\n value = fieldExpr;\n }\n result[key] = (result[key] ?? []).concat(value);\n\n return result;\n },\n {} as {\n [k: string]: string[];\n }\n );\n\n return Object.keys(groups)\n .map((key) => {\n const group = groups[key];\n\n // 일반 prop 처리\n if (key === \"\") {\n return group.map((propName) => {\n // uuid 개별 처리\n if (propName === \"uuid\") {\n return {\n nodeType: \"plain\" as const,\n prop: {\n type: \"string\",\n name: \"uuid\",\n length: 128,\n } as StringProp,\n children: [],\n };\n }\n\n const prop = entity.props.find((p) => p.name === propName);\n if (prop === undefined) {\n console.log({ propName, groups });\n throw new Error(`${entity.id} -- 잘못된 FieldExpr ${propName}`);\n }\n return {\n nodeType: \"plain\" as const,\n prop,\n children: [],\n };\n });\n }\n\n // relation prop 처리\n const prop = entity.propsDict[key];\n if (!isRelationProp(prop)) {\n throw new Error(`잘못된 FieldExpr ${key}.${group[0]}`);\n }\n const relEntity = EntityManager.get(prop.with);\n\n // relation -One 에 id 필드 하나인 경우\n if (isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)) {\n if (group.length == 1 && (group[0] === \"id\" || group[0] == \"id?\")) {\n // id 하나만 있는지 체크해서, 하나만 있으면 상위 prop으로 id를 리턴\n const idProp = relEntity.propsDict.id;\n return {\n nodeType: \"plain\" as const,\n prop: {\n ...idProp,\n name: key + \"_id\",\n nullable: prop.nullable,\n },\n children: [],\n };\n }\n }\n\n // -One 그외의 경우 object로 리턴\n // -Many의 경우 array로 리턴\n // Recursive 로 뎁스 처리\n const children = this.fieldExprsToPropNodes(group, relEntity);\n const nodeType =\n isBelongsToOneRelationProp(prop) || isOneToOneRelationProp(prop)\n ? (\"object\" as const)\n : (\"array\" as const);\n\n return {\n prop,\n children,\n nodeType,\n };\n })\n .flat();\n }\n\n getFieldExprs(\n prefix = \"\",\n maxDepth: number = 3,\n froms: string[] = []\n ): string[] {\n return this.props\n .map((prop) => {\n const propName = [prefix, prop.name].filter((v) => v !== \"\").join(\".\");\n if (propName === prefix) {\n return null;\n }\n if (isRelationProp(prop)) {\n if (maxDepth < 0) {\n return null;\n }\n if (froms.includes(prop.with)) {\n // 역방향 relation인 경우 제외\n return null;\n }\n // 정방향 relation인 경우 recursive 콜\n const relMd = EntityManager.get(prop.with);\n return relMd.getFieldExprs(propName, maxDepth - 1, [\n ...froms,\n this.id,\n ]);\n }\n return propName;\n })\n .flat()\n .filter((f) => f !== null) as string[];\n }\n\n getTableColumns(): { name: string; type: string }[] {\n return this.props\n .map((prop) => {\n if (prop.type === \"relation\") {\n if (\n prop.relationType === \"BelongsToOne\" ||\n (prop.relationType === \"OneToOne\" && prop.hasJoinColumn === true)\n ) {\n return { name: `${prop.name}_id`, type: \"int_unsigned\" };\n } else {\n return null;\n }\n }\n return { name: prop.name, type: prop.type };\n })\n .filter(nonNullable);\n }\n\n async registerModulePaths() {\n const basePath = `${this.names.parentFs}`;\n\n // base-scheme\n EntityManager.setModulePath(`${this.id}BaseSchema`, `sonamu.generated`);\n\n // subset\n if (Object.keys(this.subsets).length > 0) {\n EntityManager.setModulePath(`${this.id}SubsetKey`, `sonamu.generated`);\n EntityManager.setModulePath(\n `${this.id}SubsetMapping`,\n `sonamu.generated`\n );\n Object.keys(this.subsets).map((subsetKey) => {\n EntityManager.setModulePath(\n `${this.id}Subset${subsetKey.toUpperCase()}`,\n `sonamu.generated`\n );\n });\n }\n\n // enums\n Object.keys(this.enumLabels).map((enumId) => {\n EntityManager.setModulePath(enumId, `sonamu.generated`);\n });\n\n // types\n const typesModulePath = `${basePath}/${this.names.parentFs}.types`;\n const typesFileDistPath = path.join(\n Sonamu.apiRootPath,\n `dist/application/${typesModulePath}.js`\n );\n\n if (await exists(typesFileDistPath)) {\n const importPath = path.relative(__dirname, typesFileDistPath);\n const t = await import(importPath);\n this.types = Object.keys(t).reduce((result, key) => {\n EntityManager.setModulePath(key, typesModulePath);\n return {\n ...result,\n [key]: t[key],\n };\n }, {});\n }\n }\n\n registerTableSpecs(): void {\n const uniqueIndexes = this.indexes.filter((idx) => idx.type === \"unique\");\n\n EntityManager.setTableSpec({\n name: this.table,\n uniqueIndexes,\n });\n }\n\n toJson(): EntityJson {\n return {\n id: this.id,\n parentId: this.parentId,\n table: this.table,\n title: this.title,\n props: this.props,\n indexes: this.indexes,\n subsets: this.subsets,\n enums: this.enumLabels,\n };\n }\n\n async save(): Promise<void> {\n // sort: subsets\n const subsetRows = this.getSubsetRows();\n this.subsets = Object.fromEntries(\n Object.entries(this.subsets).map(([subsetKey]) => {\n return [\n subsetKey,\n this.subsetRowsToSubsetFields(subsetRows, subsetKey),\n ];\n })\n );\n\n // save\n const jsonPath = path.join(\n Sonamu.apiRootPath,\n `src/application/${this.names.parentFs}/${this.names.fs}.entity.json`\n );\n const json = this.toJson();\n await writeFile(\n jsonPath,\n await prettier.format(JSON.stringify(json), {\n parser: \"json\",\n })\n );\n\n // reload\n await EntityManager.register(json);\n }\n\n getSubsetRows(\n _subsets?: { [key: string]: string[] },\n prefixes: string[] = []\n ): EntitySubsetRow[] {\n if (prefixes.length > 10) {\n return [];\n }\n\n const subsets = _subsets ?? this.subsets;\n const subsetKeys = Object.keys(subsets);\n const allFields = _.uniq(subsetKeys.map((key) => subsets[key]).flat());\n\n return this.props.map((prop) => {\n if (\n prop.type === \"relation\" &&\n allFields.find((f) =>\n f.startsWith([...prefixes, prop.name].join(\".\") + \".\")\n )\n ) {\n const relEntity = EntityManager.get(prop.with);\n const children = relEntity.getSubsetRows(subsets, [\n ...prefixes,\n `${prop.name}`,\n ]);\n\n return {\n field: prop.name,\n children,\n relationEntity: prop.with,\n prefixes,\n isOpen: children.length > 0,\n has: Object.fromEntries(\n subsetKeys.map((subsetKey) => {\n return [\n subsetKey,\n children.every((child) => child.has[subsetKey] === true),\n ];\n })\n ),\n };\n }\n\n return {\n field: prop.name,\n children: [],\n relationEntity: prop.type === \"relation\" ? prop.with : undefined,\n prefixes,\n has: Object.fromEntries(\n subsetKeys.map((subsetKey) => {\n const subsetFields = subsets[subsetKey];\n const has = subsetFields.some((f) => {\n const field = [...prefixes, prop.name].join(\".\");\n return f === field || f.startsWith(field + \".\");\n });\n return [subsetKey, has];\n })\n ),\n };\n });\n }\n\n subsetRowsToSubsetFields(\n subsetRows: EntitySubsetRow[],\n subsetKey: string\n ): string[] {\n return subsetRows\n .map((subsetRow) => {\n if (subsetRow.children.length > 0) {\n return this.subsetRowsToSubsetFields(subsetRow.children, subsetKey);\n } else if (subsetRow.has[subsetKey]) {\n return subsetRow.prefixes.concat(subsetRow.field).join(\".\");\n } else {\n return null;\n }\n })\n .filter(nonNullable)\n .flat();\n }\n\n async createProp(prop: EntityProp, at?: number): Promise<void> {\n if (!at) {\n this.props.push(prop);\n } else {\n this.props.splice(at, 0, prop);\n }\n await this.save();\n }\n\n analyzeSubsetField(subsetField: string): {\n entityId: string;\n propName: string;\n }[] {\n const arr = subsetField.split(\".\");\n\n let entityId = this.id;\n const result: {\n entityId: string;\n propName: string;\n }[] = [];\n for (let i = 0; i < arr.length; i++) {\n const propName = arr[i];\n result.push({\n entityId,\n propName,\n });\n\n const prop = EntityManager.get(entityId).props.find(\n (p) => p.name === propName\n );\n if (!prop) {\n throw new Error(`${entityId}의 잘못된 서브셋키 ${subsetField}`);\n }\n if (isRelationProp(prop)) {\n entityId = prop.with;\n }\n }\n return result;\n }\n\n async modifyProp(newProp: EntityProp, at: number): Promise<void> {\n // 이전 프롭 이름 저장\n const oldName = this.props[at].name;\n\n // 저장할 엔티티\n const entities: Entity[] = [this];\n\n // 이름이 바뀐 경우\n if (oldName !== newProp.name) {\n // 전체 엔티티에서 현재 수정된 프롭을 참조하고 있는 모든 서브셋필드 찾아서 수정\n const allEntityIds = EntityManager.getAllIds();\n for (const relEntityId of allEntityIds) {\n const relEntity = EntityManager.get(relEntityId);\n const relEntitySubsetKeys = Object.keys(relEntity.subsets);\n for (const subsetKey of relEntitySubsetKeys) {\n const subset = relEntity.subsets[subsetKey];\n\n // 서브셋 필드를 순회하며, 엔티티-프롭 단위로 분석한 후 현재 엔티티-프롭과 일치하는 경우 수정 처리\n const modifiedSubsetFields = subset.map((subsetField) => {\n const analyzed = relEntity.analyzeSubsetField(subsetField);\n const modified = analyzed.map((a) =>\n a.propName === oldName && a.entityId === this.id\n ? {\n ...a,\n propName: newProp.name,\n }\n : a\n );\n // 분석한 필드를 다시 서브셋 필드로 복구\n return modified.map((a) => a.propName).join(\".\");\n });\n\n if (subset.join(\",\") !== modifiedSubsetFields.join(\",\")) {\n relEntity.subsets[subsetKey] = modifiedSubsetFields;\n entities.push(relEntity);\n }\n }\n }\n }\n\n // 프롭 수정\n this.props[at] = newProp;\n\n await Promise.all(entities.map(async (entity) => entity.save()));\n }\n\n async delProp(at: number): Promise<void> {\n // 이전 프롭 이름 저장\n const oldName = this.props[at].name;\n\n // 저장할 엔티티\n const entities: Entity[] = [this];\n\n // 전체 엔티티에서 현재 삭제된 프롭을 참조하고 있는 모든 서브셋필드 찾아서 제외\n const allEntityIds = EntityManager.getAllIds();\n for (const relEntityId of allEntityIds) {\n const relEntity = EntityManager.get(relEntityId);\n const relEntitySubsetKeys = Object.keys(relEntity.subsets);\n for (const subsetKey of relEntitySubsetKeys) {\n const subset = relEntity.subsets[subsetKey];\n // 서브셋 필드를 순회하며, 엔티티-프롭 단위로 분석한 후 현재 엔티티-프롭과 일치하는 경우 이후의 필드를 제외\n const modifiedSubsetFields = subset\n .map((subsetField) => {\n const analyzed = relEntity.analyzeSubsetField(subsetField);\n if (\n analyzed.find(\n (a) => a.propName === oldName && a.entityId === this.id\n )\n ) {\n return null;\n } else {\n return subsetField;\n }\n })\n .filter(nonNullable);\n\n if (subset.join(\",\") !== modifiedSubsetFields.join(\",\")) {\n relEntity.subsets[subsetKey] = modifiedSubsetFields;\n entities.push(relEntity);\n }\n }\n }\n\n // 현재 엔티티의 인덱스에서 제외\n EntityManager.get(this.id).indexes.map((index) => {\n index.columns = index.columns.filter((col) => col !== oldName);\n });\n\n // 프롭 삭제\n this.props.splice(at, 1);\n\n await Promise.all(entities.map(async (entity) => entity.save()));\n }\n\n getEntityIdFromSubsetField(subsetField: string): string {\n if (subsetField.includes(\".\") === false) {\n return this.id;\n }\n\n // 서브셋 필드의 마지막은 프롭이므로 제외\n const arr = subsetField.split(\".\").slice(0, -1);\n\n // 서브셋 필드를 내려가면서 마지막으로 relation된 엔티티를 찾음\n const lastEntityId = arr.reduce((entityId, field) => {\n const relProp = EntityManager.get(entityId).props.find(\n (p) => p.name === field\n );\n if (!relProp || relProp.type !== \"relation\") {\n console.debug({ arr, thisId: this.id, entityId, field });\n throw new Error(`잘못된 서브셋키 ${subsetField}`);\n }\n return relProp.with;\n }, this.id);\n return lastEntityId;\n }\n\n async moveProp(at: number, to: number): Promise<void> {\n const prop = this.props[at];\n const newProps = [...this.props];\n newProps.splice(to, 0, prop);\n newProps.splice(at < to ? at : at + 1, 1);\n this.props = newProps;\n\n await this.save();\n }\n}\n"],"names":["Entity","id","parentId","table","title","props","indexes","subsets","enums","names","propsDict","relations","types","enumLabels","inflection","underscore","pluralize","map","prop","isEnumProp","includes","replace","reduce","result","name","filter","isRelationProp","Object","fromEntries","entries","key","enumLabel","z","enum","keys","parentFs","dasherize","toLowerCase","fs","module","getSubsetQuery","subsetKey","subset","resolveSubsetQuery","prefix","fields","isAlreadyOuterJoined","subsetGroup","_","groupBy","field","split","rel","r","groupKey","realFields","isVirtualProp","virtualFields","select","concat","virtual","relation","undefined","Error","relEntity","EntityManager","get","with","isOneToOneRelationProp","isBelongsToOneRelationProp","relFields","slice","join","length","innerOrOuter","hasJoinColumn","nullable","relSubsetQuery","joinAs","fromTable","joinClause","customJoinClause","custom","from","to","joins","push","as","loaders","convertedLoaders","loader","newAs","manyJoin","oneJoins","isHasManyRelationProp","isManyToManyRelationProp","fromCol","fromColumn","idField","toTable","toCol","joinColumn","through","joinTable","singularize","fieldExprsToPropNodes","fieldExprs","entity","groups","fieldExpr","value","elseExpr","group","propName","nodeType","type","children","find","p","console","log","idProp","flat","getFieldExprs","maxDepth","froms","v","relMd","f","getTableColumns","relationType","nonNullable","registerModulePaths","basePath","typesModulePath","typesFileDistPath","importPath","t","setModulePath","toUpperCase","enumId","path","Sonamu","apiRootPath","exists","relative","__dirname","registerTableSpecs","uniqueIndexes","idx","setTableSpec","toJson","save","subsetRows","jsonPath","json","getSubsetRows","subsetRowsToSubsetFields","prettier","format","JSON","stringify","parser","writeFile","register","_subsets","prefixes","subsetKeys","allFields","uniq","startsWith","relationEntity","isOpen","has","every","child","subsetFields","some","subsetRow","createProp","at","splice","analyzeSubsetField","subsetField","arr","i","entityId","modifyProp","newProp","oldName","entities","allEntityIds","getAllIds","relEntityId","relEntitySubsetKeys","modifiedSubsetFields","analyzed","modified","a","Promise","all","delProp","index","columns","col","getEntityIdFromSubsetField","lastEntityId","relProp","debug","thisId","moveProp","newProps"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/exceptions/error-handler.ts"],"sourcesContent":["import { FastifyInstance } from \"fastify\";\nimport { ZodIssue } from \"zod\";\nimport { isSoException } from \"./so-exceptions\";\n\nexport function setupErrorHandler(server: FastifyInstance) {\n server.setErrorHandler((error, request, reply) => {\n error.statusCode ??= 400;\n\n if (isSoException(error) && error.payload && Array.isArray(error.payload)) {\n const issues = error.payload as ZodIssue[];\n const [issue] = issues;\n const message = `${issue.message} (${issue.path.join(\"/\")})`;\n\n request.log.error(`${error.statusCode} ${message}`);\n reply.status(error.statusCode <= 501 ? error.statusCode : 501).send({\n name: error.name,\n code: error.code,\n message: message,\n validationErrors: error.validation,\n issues,\n });\n } else {\n request.log.error(`${error.statusCode} ${error.message}`);\n reply.status(error.statusCode <= 501 ? error.statusCode : 501).send({\n name: error.name,\n code: error.code,\n message: error.message,\n validationErrors: error.validation,\n });\n }\n });\n}\n"],"names":["setupErrorHandler","server","setErrorHandler","error","request","reply","statusCode","isSoException","payload","Array","isArray","issues","issue","message","path","join","log","status","send","name","code","validationErrors","validation"],"mappings":"oGAIgBA,2DAAAA,+CAFc,62CAEvB,SAASA,kBAAkBC,MAAuB,EACvDA,OAAOC,eAAe,CAAC,SAACC,MAAOC,QAASC,WACtCF,sBAAAA,eAAAA,OAAAA,OAAMG,qDAANH,OAAMG,WAAe,IAErB,GAAIC,GAAAA,2BAAa,EAACJ,QAAUA,MAAMK,OAAO,EAAIC,MAAMC,OAAO,CAACP,MAAMK,OAAO,EAAG,CACzE,IAAMG,OAASR,MAAMK,OAAO,CAC5B,IAAgBG,yBAAAA,UAATC,MAASD,WAChB,IAAME,QAAU,AAAC,GAAoBD,OAAlBA,MAAMC,OAAO,CAAC,MAAyB,OAArBD,MAAME,IAAI,CAACC,IAAI,CAAC,KAAK,KAE1DX,QAAQY,GAAG,CAACb,KAAK,CAAC,AAAC,GAAsBU,OAApBV,MAAMG,UAAU,CAAC,KAAW,OAARO,UACzCR,MAAMY,MAAM,CAACd,MAAMG,UAAU,EAAI,IAAMH,MAAMG,UAAU,CAAG,KAAKY,IAAI,CAAC,CAClEC,KAAMhB,MAAMgB,IAAI,CAChBC,KAAMjB,MAAMiB,IAAI,CAChBP,QAASA,QACTQ,iBAAkBlB,MAAMmB,UAAU,CAClCX,OAAAA,MACF,EACF,KAAO,CACLP,QAAQY,GAAG,CAACb,KAAK,CAAC,AAAC,GAAsBA,OAApBA,MAAMG,UAAU,CAAC,KAAiB,OAAdH,MAAMU,OAAO,GACtDR,MAAMY,MAAM,CAACd,MAAMG,UAAU,EAAI,IAAMH,MAAMG,UAAU,CAAG,KAAKY,IAAI,CAAC,CAClEC,KAAMhB,MAAMgB,IAAI,CAChBC,KAAMjB,MAAMiB,IAAI,CAChBP,QAASV,MAAMU,OAAO,CACtBQ,iBAAkBlB,MAAMmB,UAAU,AACpC,EACF,CACF,EACF"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/exceptions/so-exceptions.ts"],"sourcesContent":["export abstract class SoException extends Error {\n constructor(\n public readonly statusCode: number,\n public message: string,\n public payload?: unknown\n ) {\n super(message);\n }\n}\n\nexport function isSoException(err: any): err is SoException {\n return err.statusCode !== undefined;\n}\n\n/*\n\t잘못된 매개변수 등 요청사항에 문제가 있는 경우\n*/\nexport class BadRequestException extends SoException {\n constructor(\n public message = \"Bad Request\",\n public payload?: unknown\n ) {\n super(400, message, payload);\n }\n}\n\n/*\n\t로그인이 반드시 필요한 케이스에 로그아웃 상태인 경우 / 접근 권한이 없는 요청시\n*/\nexport class UnauthorizedException extends SoException {\n constructor(\n public message = \"Unauthorized\",\n public payload?: unknown\n ) {\n super(401, message, payload);\n }\n}\n\n/*\n\t존재하지 않는 레코드에 접근시\n*/\nexport class NotFoundException extends SoException {\n constructor(\n public message = \"Not Found\",\n public payload?: unknown\n ) {\n super(404, message, payload);\n }\n}\n\n/*\n\t현재 상태에서 처리가 불가능한 케이스\n*/\nexport class ServiceUnavailableException extends SoException {\n constructor(\n public message = \"Service Unavailable\",\n public payload?: unknown\n ) {\n super(503, message, payload);\n }\n}\n\n/*\n\t내부 처리 로직 (외부 API 콜 포함) 오류 발생시\n*/\nexport class InternalServerErrorException extends SoException {\n constructor(\n public message = \"Internal Server Error\",\n public payload?: unknown\n ) {\n super(500, message, payload);\n }\n}\n\n/*\n\t이미 처리함\n*/\nexport class AlreadyProcessedException extends SoException {\n constructor(\n public message = \"Already Processed\",\n public payload?: unknown\n ) {\n super(541, message, payload);\n }\n}\n\n/*\n\t중복 허용하지 않는 케이스에 중복 요청\n*/\nexport class DuplicateRowException extends SoException {\n constructor(\n public message = \"Duplicate Row\",\n public payload?: unknown\n ) {\n super(542, message, payload);\n }\n}\n\n/*\n\t뭔가를 하려고 했으나 대상이 없음\n*/\nexport class TargetNotFoundException extends SoException {\n constructor(\n public message = \"Target Not Found\",\n public payload?: unknown\n ) {\n super(520, message, payload);\n }\n}\n"],"names":["AlreadyProcessedException","BadRequestException","DuplicateRowException","InternalServerErrorException","NotFoundException","ServiceUnavailableException","SoException","TargetNotFoundException","UnauthorizedException","isSoException","statusCode","message","payload","Error","err","undefined"],"mappings":"mPA6EaA,mCAAAA,+BA5DAC,6BAAAA,yBAwEAC,+BAAAA,2BAxBAC,sCAAAA,kCAxBAC,2BAAAA,uBAYAC,qCAAAA,iCArDSC,qBAAAA,iBAqGTC,iCAAAA,6BAxEAC,+BAAAA,2BAnBGC,uBAAAA,ijGAVT,IAAA,AAAeH,yBAAf,wCAAeA,6BAAAA,YAElB,AAAgBI,UAAkB,CAClC,AAAOC,OAAe,CACtB,AAAOC,OAAiB,yBAJNN,6BAMlB,iBANkBA,aAMZK,8IAJUD,WAAAA,iBACTC,QAAAA,cACAC,QAAAA,4BAJWN,gCAAoBO,QAUnC,SAASJ,cAAcK,GAAQ,EACpC,OAAOA,IAAIJ,UAAU,GAAKK,SAC5B,CAKO,IAAA,AAAMd,iCAAN,6CAAMA,0CAAAA,0BAET,AAAOU,QAAP,uDAAiB,cACjB,AAAOC,sEAHEX,qCAKT,iBALSA,qBAKH,IAAKU,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEX,qBAA4BK,aAYlC,IAAA,AAAME,mCAAN,6CAAMA,4CAAAA,4BAET,AAAOG,QAAP,uDAAiB,eACjB,AAAOC,sEAHEJ,uCAKT,iBALSA,uBAKH,IAAKG,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEJ,uBAA8BF,aAYpC,IAAA,AAAMF,+BAAN,6CAAMA,wCAAAA,wBAET,AAAOO,QAAP,uDAAiB,YACjB,AAAOC,sEAHER,mCAKT,iBALSA,mBAKH,IAAKO,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHER,mBAA0BE,aAYhC,IAAA,AAAMD,yCAAN,6CAAMA,kDAAAA,kCAET,AAAOM,QAAP,uDAAiB,sBACjB,AAAOC,sEAHEP,6CAKT,iBALSA,6BAKH,IAAKM,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEP,6BAAoCC,aAY1C,IAAA,AAAMH,0CAAN,6CAAMA,mDAAAA,mCAET,AAAOQ,QAAP,uDAAiB,wBACjB,AAAOC,sEAHET,8CAKT,iBALSA,8BAKH,IAAKQ,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHET,8BAAqCG,aAY3C,IAAA,AAAMN,uCAAN,6CAAMA,gDAAAA,gCAET,AAAOW,QAAP,uDAAiB,oBACjB,AAAOC,sEAHEZ,2CAKT,iBALSA,2BAKH,IAAKW,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEZ,2BAAkCM,aAYxC,IAAA,AAAMJ,mCAAN,6CAAMA,4CAAAA,4BAET,AAAOS,QAAP,uDAAiB,gBACjB,AAAOC,sEAHEV,uCAKT,iBALSA,uBAKH,IAAKS,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEV,uBAA8BI,aAYpC,IAAA,AAAMC,qCAAN,6CAAMA,8CAAAA,8BAET,AAAOI,QAAP,uDAAiB,mBACjB,AAAOC,sEAHEL,yCAKT,iBALSA,yBAKH,IAAKI,QAASC,kGAHbD,QAAAA,cACAC,QAAAA,4BAHEL,yBAAgCD"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/file-storage/driver.ts"],"sourcesContent":["import {\n DeleteObjectCommand,\n GetObjectCommand,\n PutObjectCommand,\n S3Client,\n S3ClientConfig,\n} from \"@aws-sdk/client-s3\";\nimport { getSignedUrl } from \"@aws-sdk/s3-request-presigner\";\nimport fs from \"fs/promises\";\nimport path from \"path\";\n\n/**\n * 파일 저장소의 공통 인터페이스\n */\nexport interface Driver {\n put(\n key: string,\n contents: Buffer,\n options?: { contentType?: string; visibility?: \"public\" | \"private\" }\n ): Promise<void>;\n\n del(key: string): Promise<void>;\n\n getUrl(key: string): string;\n\n getSignedUrl(key: string, expiresIn?: number): Promise<string>;\n\n destroy(): void;\n}\n\nexport type FSDriverConfig = {\n location: string;\n urlPrefix: string;\n};\n\n/**\n * 로컬 파일시스템\n */\nexport class FSDriver implements Driver {\n constructor(private config: FSDriverConfig) {}\n\n async put(key: string, contents: Buffer): Promise<void> {\n const filePath = path.join(this.config.location, key);\n const dir = path.dirname(filePath);\n\n await fs.mkdir(dir, { recursive: true });\n\n await fs.writeFile(filePath, contents);\n }\n\n async del(key: string) {\n await fs.rm(path.join(this.config.location, key));\n }\n\n getUrl(key: string): string {\n return `${this.config.urlPrefix}/${key}`;\n }\n\n // 로컬 파일시스템은 signed URL을 지원하지 않으므로 일반 URL 반환\n async getSignedUrl(key: string, _expiresIn?: number): Promise<string> {\n return this.getUrl(key);\n }\n\n destroy() {\n // 아무것도 하지 않음\n }\n}\n\nexport type S3DriverConfig = S3ClientConfig & {\n bucket: string;\n};\n\nexport class S3Driver implements Driver {\n s3: S3Client;\n\n constructor(private config: S3DriverConfig) {\n this.s3 = new S3Client(config);\n }\n\n async put(\n key: string,\n contents: Buffer,\n options?: { contentType?: string; visibility?: \"public\" | \"private\" }\n ): Promise<void> {\n await this.s3.send(\n new PutObjectCommand({\n Bucket: this.config.bucket,\n Key: key,\n Body: contents,\n ContentType: options?.contentType,\n ACL: this.getAcl(options?.visibility),\n })\n );\n }\n\n async del(key: string): Promise<void> {\n await this.s3.send(\n new DeleteObjectCommand({\n Bucket: this.config.bucket,\n Key: key,\n })\n );\n }\n\n getUrl(key: string): string {\n return `https://${this.config.bucket}.s3.${this.config.region}.amazonaws.com/${key}`;\n }\n\n async getSignedUrl(key: string, expiresIn?: number): Promise<string> {\n const command = new GetObjectCommand({\n Bucket: this.config.bucket,\n Key: key,\n });\n\n return getSignedUrl(this.s3, command, {\n expiresIn: expiresIn ?? 60 * 60 * 24 * 7,\n });\n }\n\n private getAcl(visibility?: \"public\" | \"private\") {\n if (visibility === \"public\") {\n return \"public-read\";\n }\n\n return visibility;\n }\n\n destroy() {\n this.s3.destroy();\n }\n}\n"],"names":["FSDriver","S3Driver","config","put","key","contents","filePath","dir","path","join","location","dirname","fs","mkdir","recursive","writeFile","del","rm","getUrl","urlPrefix","getSignedUrl","_expiresIn","destroy","s3","S3Client","options","send","PutObjectCommand","Bucket","bucket","Key","Body","ContentType","contentType","ACL","getAcl","visibility","DeleteObjectCommand","region","expiresIn","command","GetObjectCommand"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/file-storage/file-storage.ts"],"sourcesContent":["import type { MultipartFile } from \"@fastify/multipart\";\nimport mime from \"mime-types\";\nimport { createHash } from \"crypto\";\nimport type { Driver } from \"./driver\";\n\n/**\n * @fastify/multipart의 MultipartFile 래퍼\n */\nexport class FileStorage {\n private _file: MultipartFile;\n private _buffer?: Buffer;\n private _driver: Driver;\n\n constructor(file: MultipartFile, driver: Driver) {\n this._file = file;\n this._driver = driver;\n }\n\n /**\n * 사용자 컴퓨터의 원본 파일명\n */\n get clientName(): string {\n return this._file.filename;\n }\n\n /**\n * 파일명 (clientName의 별칭)\n */\n get filename(): string {\n return this._file.filename;\n }\n\n /**\n * HTML input 필드명\n */\n get fieldName(): string {\n return this._file.fieldname;\n }\n\n /**\n * 파일 크기 (바이트)\n */\n get size(): number {\n return this._file.file.bytesRead;\n }\n\n /**\n * 파일 확장자 (점 제외)\n */\n get extname(): string | false {\n return mime.extension(this._file.mimetype);\n }\n\n get mimetype(): string {\n return this._file.mimetype;\n }\n\n get encoding(): string {\n return this._file.encoding;\n }\n\n async toBuffer(): Promise<Buffer> {\n if (!this._buffer) {\n this._buffer = await this._file.toBuffer();\n }\n return this._buffer;\n }\n\n async md5(): Promise<string> {\n const buffer = await this.toBuffer();\n return createHash(\"md5\").update(buffer).digest(\"hex\");\n }\n\n /**\n * 파일을 저장소에 저장\n *\n * @example\n * ```typescript\n * const { file } = Sonamu.getUploadContext();\n * const url = await file.saveToDisk('uploads/avatar.png');\n * ```\n */\n async saveToDisk(\n key: string,\n options?: { contentType?: string; visibility?: \"public\" | \"private\" }\n ): Promise<string> {\n const buffer = await this.toBuffer();\n\n await this._driver.put(key, buffer, {\n contentType: options?.contentType ?? this.mimetype,\n visibility: options?.visibility,\n });\n\n return this._driver.getSignedUrl(key);\n }\n\n get raw(): MultipartFile {\n return this._file;\n }\n}\n"],"names":["FileStorage","file","driver","_file","_buffer","_driver","clientName","filename","fieldName","fieldname","size","bytesRead","extname","mime","extension","mimetype","encoding","toBuffer","md5","buffer","createHash","update","digest","saveToDisk","key","options","put","contentType","visibility","getSignedUrl","raw"],"mappings":"oGAQaA,qDAAAA,4EAPI,mCACU,+qFAMpB,IAAA,AAAMA,yBAAN,iCAAMA,YAKCC,IAAmB,CAAEC,MAAc,yBALpCF,aACX,sBAAQG,QAAR,KAAA,GACA,sBAAQC,UAAR,KAAA,GACA,sBAAQC,UAAR,KAAA,EAGE,CAAA,IAAI,CAACF,KAAK,CAAGF,IACb,CAAA,IAAI,CAACI,OAAO,CAAGH,qBAPNF,cAaPM,IAAAA,iBAAJ,eACE,OAAO,IAAI,CAACH,KAAK,CAACI,QAAQ,AAC5B,IAKIA,IAAAA,eAAJ,eACE,OAAO,IAAI,CAACJ,KAAK,CAACI,QAAQ,AAC5B,IAKIC,IAAAA,gBAAJ,eACE,OAAO,IAAI,CAACL,KAAK,CAACM,SAAS,AAC7B,IAKIC,IAAAA,WAAJ,eACE,OAAO,IAAI,CAACP,KAAK,CAACF,IAAI,CAACU,SAAS,AAClC,IAKIC,IAAAA,cAAJ,eACE,OAAOC,kBAAI,CAACC,SAAS,CAAC,IAAI,CAACX,KAAK,CAACY,QAAQ,CAC3C,IAEIA,IAAAA,eAAJ,eACE,OAAO,IAAI,CAACZ,KAAK,CAACY,QAAQ,AAC5B,IAEIC,IAAAA,eAAJ,eACE,OAAO,IAAI,CAACb,KAAK,CAACa,QAAQ,AAC5B,IAEMC,IAAAA,iBAAN,SAAMA,kIACA,CAAC,IAAI,CAACb,OAAO,CAAb,cACF,IAAI,CAAW,SAAM,IAAI,CAACD,KAAK,CAACc,QAAQ,WAAxC,EAAKb,OAAO,CAAG,oCAEjB,SAAO,IAAI,CAACA,OAAO,IACrB,iBAEMc,IAAAA,YAAN,SAAMA,gDACEC,8EAAS,SAAM,IAAI,CAACF,QAAQ,WAA5BE,OAAS,cACf,SAAOC,GAAAA,kBAAU,EAAC,OAAOC,MAAM,CAACF,QAAQG,MAAM,CAAC,UACjD,iBAWMC,IAAAA,mBAAN,SAAMA,WACJC,GAAW,CACXC,OAAqE,4CAE/DN,OAGSM,4FAHA,SAAM,IAAI,CAACR,QAAQ,WAA5BE,OAAS,cAEf,SAAM,IAAI,CAACd,OAAO,CAACqB,GAAG,CAACF,IAAKL,OAAQ,CAClCQ,YAAaF,CAAAA,qBAAAA,gBAAAA,wBAAAA,QAASE,WAAW,UAApBF,8BAAAA,qBAAwB,IAAI,CAACV,QAAQ,CAClDa,UAAU,CAAEH,gBAAAA,wBAAAA,QAASG,UAAU,AACjC,WAHA,cAKA,SAAO,IAAI,CAACvB,OAAO,CAACwB,YAAY,CAACL,QACnC,iBAEIM,IAAAA,UAAJ,eACE,OAAO,IAAI,CAAC3B,KAAK,AACnB,YA1FWH"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export type * from \"./api/context\";\nexport * from \"./api/decorators\";\nexport * from \"./api/sonamu\";\nexport * from \"./database/base-model\";\nexport * from \"./api/base-frame\";\nexport * from \"./database/db\";\nexport * from \"./database/upsert-builder\";\nexport * from \"./database/puri\";\nexport * from \"./database/puri-wrapper\";\nexport * from \"./database/puri.types\";\nexport * from \"./exceptions/error-handler\";\nexport * from \"./exceptions/so-exceptions\";\nexport * from \"./stream/sse\";\nexport * from \"./types/types\";\nexport * from \"./utils/controller\";\nexport * from \"./utils/model\";\nexport * from \"./utils/utils\";\nexport * from \"./testing/fixture-manager\";\nexport * from \"./entity/entity-manager\";\nexport * from \"./entity/entity\";\nexport * from \"./migration/migrator\";\nexport * from \"./migration/types\";\nexport * from \"./file-storage/driver\";\n\n// export * from \"./api/code-converters\";\n// export * from \"./entity/entity-utils\";\n// export * from \"./syncer/syncer\";\n"],"names":[],"mappings":"2FACc,kDACA,8CACA,uDACA,kDACA,+CACA,2DACA,iDACA,yDACA,uDACA,4DACA,4DACA,8CACA,+CACA,oDACA,+CACA,+CACA,2DACA,yDACA,iDACA,sDACA,mDACA"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/migration/code-generation.ts"],"sourcesContent":["import _ from \"lodash\";\nimport prettier from \"prettier\";\nimport equal from \"fast-deep-equal\";\nimport {\n GenMigrationCode,\n MigrationColumn,\n MigrationForeign,\n MigrationIndex,\n MigrationSet,\n} from \"../types/types\";\n\n/**\n * 테이블 생성하는 케이스 - 컬럼/인덱스 생성\n */\nasync function generateCreateCode_ColumnAndIndexes(\n table: string,\n columns: MigrationColumn[],\n indexes: MigrationIndex[]\n): Promise<GenMigrationCode> {\n // fulltext index 분리\n const [ngramIndexes, standardIndexes] = _.partition(\n indexes,\n (i) => i.type === \"fulltext\" && i.parser === \"ngram\"\n );\n\n // 컬럼, 인덱스 처리\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `await knex.schema.createTable(\"${table}\", (table) => {`,\n \"// columns\",\n ...genColumnDefinitions(columns),\n \"\",\n \"// indexes\",\n ...standardIndexes.map((index) => genIndexDefinition(index, table)),\n \"});\",\n // ngram은 knex.raw로 처리하므로 createTable 밖에서 실행\n ...ngramIndexes.map((index) => genIndexDefinition(index, table)),\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n ` return knex.schema.dropTable(\"${table}\");`,\n \"}\",\n ];\n return {\n table,\n type: \"normal\",\n title: `create__${table}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n };\n}\n\n/**\n * MigrationColumn[] 읽어서 컬럼 정의하는 구문 생성\n */\nfunction genColumnDefinitions(columns: MigrationColumn[]): string[] {\n return columns.map((column) => {\n const chains: string[] = [];\n if (column.name === \"id\") {\n return `table.increments().primary();`;\n }\n\n // FIXME: float(M,D) deprecated -> decimal(M,D) 이용하도록 하고, float/double 처리 추가\n if (column.type === \"float\" || column.type === \"decimal\") {\n chains.push(\n `${column.type}('${column.name}', ${column.precision}, ${column.scale})`\n );\n } else {\n // type, length\n let columnType = column.type;\n let extraType: string | undefined;\n if (columnType.includes(\"text\") && columnType !== \"text\") {\n extraType = columnType;\n columnType = \"text\";\n }\n chains.push(\n `${columnType}('${column.name}'${\n column.length ? `, ${column.length}` : \"\"\n }${extraType ? `, '${extraType}'` : \"\"})`\n );\n }\n if (column.unsigned) {\n chains.push(\"unsigned()\");\n }\n\n // nullable\n chains.push(column.nullable ? \"nullable()\" : \"notNullable()\");\n\n // defaultTo\n if (column.defaultTo !== undefined) {\n if (\n typeof column.defaultTo === \"string\" &&\n column.defaultTo.startsWith(`\"`)\n ) {\n chains.push(`defaultTo(${column.defaultTo})`);\n } else {\n chains.push(`defaultTo(knex.raw('${column.defaultTo}'))`);\n }\n }\n\n return `table.${chains.join(\".\")};`;\n });\n}\n\n/**\n * 개별 인덱스 정의 생성\n */\nfunction genIndexDefinition(index: MigrationIndex, table: string) {\n const methodMap = {\n index: \"index\",\n fulltext: \"index\",\n unique: \"unique\",\n };\n\n if (index.type === \"fulltext\" && index.parser === \"ngram\") {\n const indexName = `${table}_${index.columns.join(\"_\")}_index`;\n return `await knex.raw(\\`ALTER TABLE ${table} ADD FULLTEXT INDEX ${indexName} (${index.columns.join(\n \", \"\n )}) WITH PARSER ngram\\`);`;\n }\n\n return `table.${methodMap[index.type]}([${index.columns\n .map((col) => `'${col}'`)\n .join(\",\")}]${index.type === \"fulltext\" ? \", undefined, 'FULLTEXT'\" : \"\"})`;\n}\n\n/**\n * 테이블 생성하는 케이스 - FK 생성\n */\nasync function generateCreateCode_Foreign(\n table: string,\n foreigns: MigrationForeign[]\n): Promise<GenMigrationCode[]> {\n if (foreigns.length === 0) {\n return [];\n }\n\n const { up, down } = genForeignDefinitions(table, foreigns);\n if (up.length === 0 && down.length === 0) {\n console.log(\"fk 가 뭔가 다릅니다\");\n return [];\n }\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// create fk\",\n ...up,\n \"});\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n \"// drop fk\",\n ...down,\n \"});\",\n \"}\",\n ];\n\n const foreignKeysString = foreigns\n .map((foreign) => foreign.columns.join(\"_\"))\n .join(\"_\");\n return [\n {\n table,\n type: \"foreign\",\n title: `foreign__${table}__${foreignKeysString}`,\n formatted: await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n }),\n },\n ];\n}\n\n/**\n * MigrationForeign[] 읽어서 외부키 constraint 정의하는 구문 생성\n */\nfunction genForeignDefinitions(\n table: string,\n foreigns: MigrationForeign[]\n): { up: string[]; down: string[] } {\n return foreigns.reduce(\n (r, foreign) => {\n const columnsStringQuote = foreign.columns\n .map((col) => `'${col.replace(`${table}.`, \"\")}'`)\n .join(\",\");\n r.up.push(\n `table.foreign('${foreign.columns.join(\",\")}')\n .references('${foreign.to}')\n .onUpdate('${foreign.onUpdate}')\n .onDelete('${foreign.onDelete}')`\n );\n r.down.push(`table.dropForeign([${columnsStringQuote}])`);\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n}\n\n/**\n * 테이블 변경 케이스 - 컬럼/인덱스 변경\n */\nasync function generateAlterCode_ColumnAndIndexes(\n table: string,\n entityColumns: MigrationColumn[],\n entityIndexes: MigrationIndex[],\n dbColumns: MigrationColumn[],\n dbIndexes: MigrationIndex[],\n dbForeigns: MigrationForeign[]\n): Promise<GenMigrationCode[]> {\n /*\n 세부 비교 후 다른점 찾아서 코드 생성\n\n 1. 컬럼갯수 다름: MD에 있으나, DB에 없다면 추가\n 2. 컬럼갯수 다름: MD에 없으나, DB에 있다면 삭제\n 3. 그외 컬럼(컬럼 갯수가 동일하거나, 다른 경우 동일한 컬럼끼리) => alter\n 4. 다른거 다 동일하고 index만 변경되는 경우\n\n ** 컬럼명을 변경하는 경우는 따로 핸들링하지 않음\n => drop/add 형태의 마이그레이션 코드가 생성되는데, 수동으로 rename 코드로 수정하여 처리\n */\n\n // 각 컬럼 이름 기준으로 add, drop, alter 여부 확인\n const alterColumnsTo = getAlterColumnsTo(entityColumns, dbColumns);\n\n // 추출된 컬럼들을 기준으로 각각 라인 생성\n const alterColumnLinesTo = getAlterColumnLinesTo(\n alterColumnsTo,\n entityColumns,\n table,\n dbForeigns\n );\n\n // 인덱스의 add, drop 여부 확인\n const alterIndexesTo = getAlterIndexesTo(entityIndexes, dbIndexes);\n\n // fulltext index 분리\n const [ngramIndexes, standardIndexes] = _.partition(\n alterIndexesTo.add,\n (i) => i.type === \"fulltext\" && i.parser === \"ngram\"\n );\n\n // 인덱스가 삭제되는 경우, 컬럼과 같이 삭제된 케이스에는 drop에서 제외해야함!\n const indexNeedsToDrop = alterIndexesTo.drop.filter(\n (index) =>\n index.columns.every((colName) =>\n alterColumnsTo.drop.map((col) => col.name).includes(colName)\n ) === false\n );\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `await knex.schema.alterTable(\"${table}\", (table) => {`,\n // 1. add column\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.up : []),\n // 2. drop column\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.up : []),\n // 3. alter column\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.up : []),\n // 4. add index\n ...standardIndexes.map((index) => genIndexDefinition(index, table)),\n // 5. drop index\n ...indexNeedsToDrop.map(genIndexDropDefinition),\n \"});\",\n // ngram은 knex.raw로 처리하므로 alterTable 밖에서 실행\n ...ngramIndexes.map((index) => genIndexDefinition(index, table)),\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...(alterColumnsTo.add.length > 0 ? alterColumnLinesTo.add.down : []),\n ...(alterColumnsTo.drop.length > 0 ? alterColumnLinesTo.drop.down : []),\n ...(alterColumnsTo.alter.length > 0 ? alterColumnLinesTo.alter.down : []),\n ...alterIndexesTo.add\n .filter(\n (index) =>\n index.columns.every((colName) =>\n alterColumnsTo.add.map((col) => col.name).includes(colName)\n ) === false\n )\n .map(genIndexDropDefinition),\n ...indexNeedsToDrop.map((index) => genIndexDefinition(index, table)),\n \"});\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n ...([\"add\", \"drop\", \"alter\"] as const)\n .map((action) => {\n const len = alterColumnsTo[action].length;\n if (len > 0) {\n return action + len;\n }\n return null;\n })\n .filter((part) => part !== null),\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n}\n\n/**\n * 각 컬럼 이름 기준으로 add, drop, alter 여부 확인\n */\nfunction getAlterColumnsTo(\n entityColumns: MigrationColumn[],\n dbColumns: MigrationColumn[]\n) {\n const columnsTo = {\n add: [] as MigrationColumn[],\n drop: [] as MigrationColumn[],\n alter: [] as MigrationColumn[],\n };\n\n // 컬럼명 기준 비교\n const extraColumns = {\n db: _.differenceBy(dbColumns, entityColumns, (col) => col.name),\n entity: _.differenceBy(entityColumns, dbColumns, (col) => col.name),\n };\n if (extraColumns.entity.length > 0) {\n columnsTo.add = columnsTo.add.concat(extraColumns.entity);\n }\n if (extraColumns.db.length > 0) {\n columnsTo.drop = columnsTo.drop.concat(extraColumns.db);\n }\n\n // 동일 컬럼명의 세부 필드 비교\n const sameDbColumns = _.intersectionBy(\n dbColumns,\n entityColumns,\n (col) => col.name\n );\n const sameMdColumns = _.intersectionBy(\n entityColumns,\n dbColumns,\n (col) => col.name\n );\n columnsTo.alter = _.differenceWith(sameDbColumns, sameMdColumns, (a, b) =>\n equal(a, b)\n );\n\n return columnsTo;\n}\n\n/**\n * 추출된 컬럼들을 기준으로 각각 라인 생성\n */\nfunction getAlterColumnLinesTo(\n columnsTo: ReturnType<typeof getAlterColumnsTo>,\n entityColumns: MigrationColumn[],\n table: string,\n dbForeigns: MigrationForeign[]\n) {\n let linesTo = {\n add: {\n up: [] as string[],\n down: [] as string[],\n },\n drop: {\n up: [] as string[],\n down: [] as string[],\n },\n alter: {\n up: [] as string[],\n down: [] as string[],\n },\n };\n\n linesTo.add = {\n up: [\"// add\", ...genColumnDefinitions(columnsTo.add)],\n down: [\n \"// rollback - add\",\n `table.dropColumns(${columnsTo.add\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n };\n\n // drop할 컬럼에 걸린 FK 찾기\n const dropColumnNames = columnsTo.drop.map((col) => col.name);\n const fkToDropBeforeColumn = dbForeigns.filter((fk) =>\n fk.columns.some((col) => dropColumnNames.includes(col))\n );\n\n const dropFkLines = fkToDropBeforeColumn.map((fk) => {\n const columnsStringQuote = fk.columns.map((col) => `'${col}'`).join(\",\");\n return `table.dropForeign([${columnsStringQuote}])`;\n });\n\n const restoreFkLines = genForeignDefinitions(table, fkToDropBeforeColumn).up;\n\n linesTo.drop = {\n up: [\n ...(dropFkLines.length > 0\n ? [\"// drop foreign keys on columns to be dropped\", ...dropFkLines]\n : []),\n \"// drop columns\",\n `table.dropColumns(${columnsTo.drop\n .map((col) => `'${col.name}'`)\n .join(\", \")})`,\n ],\n down: [\n \"// rollback - drop columns\",\n ...genColumnDefinitions(columnsTo.drop),\n ...(restoreFkLines.length > 0\n ? [\"// restore foreign keys\", ...restoreFkLines]\n : []),\n ],\n };\n linesTo.alter = columnsTo.alter.reduce(\n (r, dbColumn) => {\n const entityColumn = entityColumns.find(\n (col) => col.name == dbColumn.name\n );\n if (entityColumn === undefined) {\n return r;\n }\n\n // 컬럼 변경사항\n const columnDiffUp = _.difference(\n genColumnDefinitions([entityColumn]),\n genColumnDefinitions([dbColumn])\n );\n const columnDiffDown = _.difference(\n genColumnDefinitions([dbColumn]),\n genColumnDefinitions([entityColumn])\n );\n if (columnDiffUp.length > 0) {\n r.up = [\n ...r.up,\n \"// alter column\",\n ...columnDiffUp.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n r.down = [\n ...r.down,\n \"// rollback - alter column\",\n ...columnDiffDown.map((l) => l.replace(\";\", \"\") + \".alter();\"),\n ];\n }\n\n return r;\n },\n {\n up: [] as string[],\n down: [] as string[],\n }\n );\n\n return linesTo;\n}\n\n/**\n * 인덱스의 add, drop 여부 확인\n */\nfunction getAlterIndexesTo(\n entityIndexes: MigrationIndex[],\n dbIndexes: MigrationIndex[]\n) {\n // 인덱스 비교\n let indexesTo = {\n add: [] as MigrationIndex[],\n drop: [] as MigrationIndex[],\n };\n const extraIndexes = {\n db: _.differenceBy(dbIndexes, entityIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n entity: _.differenceBy(entityIndexes, dbIndexes, (col) =>\n [col.type, col.columns.join(\"-\")].join(\"//\")\n ),\n };\n if (extraIndexes.entity.length > 0) {\n indexesTo.add = indexesTo.add.concat(extraIndexes.entity);\n }\n if (extraIndexes.db.length > 0) {\n indexesTo.drop = indexesTo.drop.concat(extraIndexes.db);\n }\n\n return indexesTo;\n}\n\n/**\n * 인덱스 삭제 정의 생성\n */\nfunction genIndexDropDefinition(index: MigrationIndex) {\n const methodMap = {\n index: \"Index\",\n fulltext: \"Index\",\n unique: \"Unique\",\n };\n\n return `table.drop${methodMap[index.type]}([${index.columns\n .map((columnName) => `'${columnName}'`)\n .join(\",\")}])`;\n}\n\n/**\n * 테이블 변경 케이스 - Foreign Key 변경\n */\nasync function generateAlterCode_Foreigns(\n table: string,\n entityForeigns: MigrationForeign[],\n dbForeigns: MigrationForeign[],\n droppingColumns: MigrationColumn[] = []\n): Promise<GenMigrationCode[]> {\n // console.log({ entityForeigns, dbForeigns });\n\n const getKey = (mf: MigrationForeign): string => {\n return [mf.columns.join(\"-\"), mf.to].join(\"///\");\n };\n\n // 삭제될 컬럼명 목록\n const droppingColumnNames = droppingColumns.map((col) => col.name);\n\n const fkTo = entityForeigns.reduce(\n (result, entityF) => {\n const matchingDbF = dbForeigns.find(\n (dbF) => getKey(entityF) === getKey(dbF)\n );\n if (!matchingDbF) {\n result.add.push(entityF);\n return result;\n }\n\n if (equal(entityF, matchingDbF) === false) {\n result.alterSrc.push(matchingDbF);\n result.alterDst.push(entityF);\n return result;\n }\n return result;\n },\n {\n add: [] as MigrationForeign[],\n drop: [] as MigrationForeign[],\n alterSrc: [] as MigrationForeign[],\n alterDst: [] as MigrationForeign[],\n }\n );\n\n // dbForeigns에는 있지만 entityForeigns에는 없는 경우 (삭제된 FK)\n // 단, 삭제될 컬럼의 FK는 제외 (generateAlterCode_ColumnAndIndexes에서 처리)\n dbForeigns.forEach((dbF) => {\n const matchingEntityF = entityForeigns.find(\n (entityF) => getKey(entityF) === getKey(dbF)\n );\n if (!matchingEntityF) {\n // 이 FK의 컬럼이 삭제될 컬럼 목록에 있는지 확인\n const isColumnDropping = dbF.columns.some((col) =>\n droppingColumnNames.includes(col)\n );\n // 컬럼이 삭제되지 않는 경우에만 FK drop 목록에 추가\n if (!isColumnDropping) {\n fkTo.drop.push(dbF);\n }\n }\n });\n\n const linesTo = {\n add: genForeignDefinitions(table, fkTo.add),\n drop: genForeignDefinitions(table, fkTo.drop),\n alterSrc: genForeignDefinitions(table, fkTo.alterSrc),\n alterDst: genForeignDefinitions(table, fkTo.alterDst),\n };\n\n // drop fk columns인 경우(생성될 코드 없는 경우) 패스\n const hasLines = Object.values(linesTo).some(\n (l) => l.up.length > 0 || l.down.length > 0\n );\n if (!hasLines) {\n return [];\n }\n\n const lines: string[] = [\n 'import { Knex } from \"knex\";',\n \"\",\n \"export async function up(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.drop.down,\n ...linesTo.add.up,\n ...linesTo.alterSrc.down,\n ...linesTo.alterDst.up,\n \"})\",\n \"}\",\n \"\",\n \"export async function down(knex: Knex): Promise<void> {\",\n `return knex.schema.alterTable(\"${table}\", (table) => {`,\n ...linesTo.add.down,\n ...linesTo.alterDst.down,\n ...linesTo.alterSrc.up,\n ...linesTo.drop.up,\n \"})\",\n \"}\",\n ];\n\n const formatted = await prettier.format(lines.join(\"\\n\"), {\n parser: \"typescript\",\n });\n\n const title = [\n \"alter\",\n table,\n \"foreigns\",\n // TODO 바뀌는 부분\n ].join(\"_\");\n\n return [\n {\n table,\n title,\n formatted,\n type: \"normal\",\n },\n ];\n}\n\n/**\n * 주어진 EntitySet을 기반으로 테이블 CREATE 마이그레이션 코드를 생성합니다.\n * @param entitySet\n * @returns CREATE 마이그레이션 코드\n */\nexport async function generateCreateCode(\n entitySet: MigrationSet\n): Promise<GenMigrationCode[]> {\n return [\n await generateCreateCode_ColumnAndIndexes(\n entitySet.table,\n entitySet.columns,\n entitySet.indexes\n ),\n ...(await generateCreateCode_Foreign(entitySet.table, entitySet.foreigns)),\n ];\n}\n\n/**\n * 주어진 entitySet을 목표로, dbSet을 현 상황으로 하여 테이블 ALTER 마이그레이션 코드를 생성합니다.\n * @param entitySet 현 상황의 MigrationSet\n * @param dbSet 목표 상황의 MigrationSet\n * @returns ALTER 마이그레이션 코드\n */\nexport async function generateAlterCode(\n entitySet: MigrationSet,\n dbSet: MigrationSet\n): Promise<GenMigrationCode[]> {\n const replaceColumnDefaultTo = (col: MigrationColumn) => {\n // float인 경우 기본값을 0으로 지정하는 경우 \"0.00\"으로 변환되는 케이스 대응\n if (\n col.type === \"float\" &&\n col.defaultTo &&\n String(col.defaultTo).includes('\"') === false\n ) {\n col.defaultTo = `\"${Number(col.defaultTo).toFixed(col.scale ?? 2)}\"`;\n }\n // string인 경우 기본값이 빈 스트링인 경우 대응\n if (col.type === \"string\" && col.defaultTo === \"\") {\n col.defaultTo = '\"\"';\n }\n // boolean인 경우 기본값 정규화 (MySQL에서는 TINYINT(1)로 저장되므로 0 또는 1로 정규화)\n // TODO: db.ts에 typeCase 설정 확인하여 처리하도록 수정 필요\n if (col.type === \"boolean\" && col.defaultTo !== undefined) {\n if (col.defaultTo === \"0\" || col.defaultTo.toLowerCase() === \"false\") {\n col.defaultTo = \"0\";\n } else if (col.defaultTo === \"1\" || col.defaultTo.toLowerCase() === \"true\") {\n col.defaultTo = \"1\";\n }\n }\n return col;\n };\n const entityColumns = _.sortBy(entitySet.columns, (a) => a.name).map(\n replaceColumnDefaultTo\n );\n const dbColumns = _.sortBy(dbSet.columns, (a) => a.name).map(\n replaceColumnDefaultTo\n );\n\n /* 디버깅용 코드, 특정 컬럼에서 불일치 발생할 때 확인\n const entityColumn = entitySet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n const dbColumn = dbSet.columns.find(\n (col) => col.name === \"price_krw\"\n );\n console.debug({ entityColumn, dbColumn });\n */\n\n const entityIndexes = _.sortBy(entitySet.indexes, (a) =>\n [a.type, ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1))].join(\"-\")\n );\n const dbIndexes = _.sortBy(dbSet.indexes, (a) =>\n [a.type, ...a.columns.sort((c1, c2) => (c1 > c2 ? 1 : -1))].join(\"-\")\n );\n\n const replaceNoActionOnMySQL = (f: MigrationForeign) => {\n // MySQL에서 RESTRICT와 NO ACTION은 동일함\n const { onDelete, onUpdate } = f;\n return {\n ...f,\n onUpdate: onUpdate === \"RESTRICT\" ? \"NO ACTION\" : onUpdate,\n onDelete: onDelete === \"RESTRICT\" ? \"NO ACTION\" : onDelete,\n };\n };\n\n const entityForeigns = _.sortBy(entitySet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n const dbForeigns = _.sortBy(dbSet.foreigns, (a) =>\n [a.to, ...a.columns].join(\"-\")\n ).map((f) => replaceNoActionOnMySQL(f));\n\n // 삭제될 컬럼 목록 계산\n const droppingColumns = _.differenceBy(\n dbColumns,\n entityColumns,\n (col) => col.name\n );\n\n const alterCodes: (GenMigrationCode | GenMigrationCode[] | null)[] = [];\n\n // 1. columnsAndIndexes 처리\n const isEqualColumns = equal(entityColumns, dbColumns);\n const isEqualIndexes = equal(\n entityIndexes.map((index) => _.omit(index, [\"parser\"])),\n dbIndexes\n );\n if (!isEqualColumns || !isEqualIndexes) {\n alterCodes.push(\n await generateAlterCode_ColumnAndIndexes(\n entitySet.table,\n entityColumns,\n entityIndexes,\n dbColumns,\n dbIndexes,\n dbSet.foreigns\n )\n );\n }\n\n // 2. foreigns 처리 (삭제될 컬럼 정보 전달)\n if (equal(entityForeigns, dbForeigns) === false) {\n alterCodes.push(\n await generateAlterCode_Foreigns(\n entitySet.table,\n entityForeigns,\n dbForeigns,\n droppingColumns\n )\n );\n }\n\n if (alterCodes.every((alterCode) => alterCode === null)) {\n return [];\n }\n\n return alterCodes.filter((alterCode) => alterCode !== null).flat();\n}\n"],"names":["generateAlterCode","generateCreateCode","generateCreateCode_ColumnAndIndexes","table","columns","indexes","_","ngramIndexes","standardIndexes","lines","partition","i","type","parser","genColumnDefinitions","map","index","genIndexDefinition","title","prettier","format","join","formatted","column","chains","name","push","precision","scale","columnType","extraType","includes","length","unsigned","nullable","defaultTo","undefined","startsWith","methodMap","fulltext","unique","indexName","col","generateCreateCode_Foreign","foreigns","genForeignDefinitions","up","down","foreignKeysString","console","log","foreign","reduce","r","columnsStringQuote","replace","to","onUpdate","onDelete","generateAlterCode_ColumnAndIndexes","entityColumns","entityIndexes","dbColumns","dbIndexes","dbForeigns","alterColumnsTo","alterColumnLinesTo","alterIndexesTo","indexNeedsToDrop","getAlterColumnsTo","getAlterColumnLinesTo","getAlterIndexesTo","add","drop","filter","every","colName","alter","genIndexDropDefinition","action","len","part","columnsTo","extraColumns","db","differenceBy","entity","concat","sameDbColumns","intersectionBy","sameMdColumns","differenceWith","a","b","equal","linesTo","dropColumnNames","fkToDropBeforeColumn","fk","some","dropFkLines","restoreFkLines","dbColumn","entityColumn","find","columnDiffUp","difference","columnDiffDown","l","indexesTo","extraIndexes","columnName","generateAlterCode_Foreigns","entityForeigns","droppingColumns","getKey","droppingColumnNames","fkTo","hasLines","mf","result","entityF","matchingDbF","dbF","alterSrc","alterDst","forEach","matchingEntityF","isColumnDropping","Object","values","entitySet","dbSet","replaceColumnDefaultTo","replaceNoActionOnMySQL","alterCodes","isEqualColumns","isEqualIndexes","String","Number","toFixed","toLowerCase","sortBy","sort","c1","c2","f","omit","alterCode","flat"],"mappings":"mPAspBsBA,2BAAAA,uBAnBAC,4BAAAA,gFAnoBR,uEACO,8EACH,ghKAYlB,SAAeC,oCACbC,KAAa,CACbC,OAA0B,CAC1BC,OAAyB,4CAGeC,YAAjCC,aAAcC,gBAMfC,kFANkCH,6BAAAA,eAAC,CAACI,SAAS,CACjDL,QACA,SAACM,UAAMA,EAAEC,IAAI,GAAK,YAAcD,EAAEE,MAAM,GAAK,aAFxCN,aAAiCD,eAAnBE,gBAAmBF,eAMlCG,MAAkB,CACtB,+BACA,GACA,wDACA,AAAC,kCAAuC,OAANN,MAAM,mBACxC,cALsB,OAMtB,qBAAGW,qBAAqBV,WACxB,GACA,cACA,qBAAGI,gBAAgBO,GAAG,CAAC,SAACC,cAAUC,mBAAmBD,MAAOb,WAC5D,OAEA,qBAAGI,aAAaQ,GAAG,CAAC,SAACC,cAAUC,mBAAmBD,MAAOb,WACzD,IACA,GACA,0DACA,AAAC,kCAAuC,OAANA,MAAM,OACxC,YAGAA,MAAAA,MACAS,KAAM,SACNM,MAAO,AAAC,WAAgB,OAANf,QACP,SAAMgB,iBAAQ,CAACC,MAAM,CAACX,MAAMY,IAAI,CAAC,MAAO,CACjDR,OAAQ,YACV,WANF,eAIES,UAAW,uBAIf,KAKA,SAASR,qBAAqBV,OAA0B,EACtD,OAAOA,QAAQW,GAAG,CAAC,SAACQ,QAClB,IAAMC,OAAmB,EAAE,CAC3B,GAAID,OAAOE,IAAI,GAAK,KAAM,CACxB,MAAO,+BACT,CAGA,GAAIF,OAAOX,IAAI,GAAK,SAAWW,OAAOX,IAAI,GAAK,UAAW,CACxDY,OAAOE,IAAI,CACT,AAAC,GAAkBH,OAAhBA,OAAOX,IAAI,CAAC,MAAqBW,OAAjBA,OAAOE,IAAI,CAAC,OAA0BF,OAArBA,OAAOI,SAAS,CAAC,MAAiB,OAAbJ,OAAOK,KAAK,CAAC,KAE1E,KAAO,CAEL,IAAIC,WAAaN,OAAOX,IAAI,CAC5B,IAAIkB,UACJ,GAAID,WAAWE,QAAQ,CAAC,SAAWF,aAAe,OAAQ,CACxDC,UAAYD,WACZA,WAAa,MACf,CACAL,OAAOE,IAAI,CACT,AAAC,GAAiBH,OAAfM,WAAW,MACZN,OADgBA,OAAOE,IAAI,CAAC,KAE3BK,OADDP,OAAOS,MAAM,CAAG,AAAC,KAAkB,OAAdT,OAAOS,MAAM,EAAK,IACF,OAApCF,UAAY,AAAC,MAAe,OAAVA,UAAU,KAAK,GAAG,KAE3C,CACA,GAAIP,OAAOU,QAAQ,CAAE,CACnBT,OAAOE,IAAI,CAAC,aACd,CAGAF,OAAOE,IAAI,CAACH,OAAOW,QAAQ,CAAG,aAAe,iBAG7C,GAAIX,OAAOY,SAAS,GAAKC,UAAW,CAClC,GACE,OAAOb,OAAOY,SAAS,GAAK,UAC5BZ,OAAOY,SAAS,CAACE,UAAU,CAAC,KAC5B,CACAb,OAAOE,IAAI,CAAC,AAAC,aAA6B,OAAjBH,OAAOY,SAAS,CAAC,KAC5C,KAAO,CACLX,OAAOE,IAAI,CAAC,AAAC,uBAAuC,OAAjBH,OAAOY,SAAS,CAAC,OACtD,CACF,CAEA,MAAO,AAAC,SAAyB,OAAjBX,OAAOH,IAAI,CAAC,KAAK,IACnC,EACF,CAKA,SAASJ,mBAAmBD,KAAqB,CAAEb,KAAa,EAC9D,IAAMmC,UAAY,CAChBtB,MAAO,QACPuB,SAAU,QACVC,OAAQ,QACV,EAEA,GAAIxB,MAAMJ,IAAI,GAAK,YAAcI,MAAMH,MAAM,GAAK,QAAS,CACzD,IAAM4B,UAAY,AAAC,GAAWzB,OAATb,MAAM,KAA2B,OAAxBa,MAAMZ,OAAO,CAACiB,IAAI,CAAC,KAAK,UACtD,MAAO,AAAC,+BAA2DoB,OAA5BtC,MAAM,wBAAoCa,OAAdyB,UAAU,MAE3E,OAF+EzB,MAAMZ,OAAO,CAACiB,IAAI,CACjG,MACA,yBACJ,CAEA,MAAO,AAAC,SAAkCL,OAA1BsB,SAAS,CAACtB,MAAMJ,IAAI,CAAC,CAAC,MAEtBI,OAF0BA,MAAMZ,OAAO,CACpDW,GAAG,CAAC,SAAC2B,WAAQ,AAAC,IAAO,OAAJA,IAAI,OACrBrB,IAAI,CAAC,KAAK,KAA8D,OAA3DL,MAAMJ,IAAI,GAAK,WAAa,0BAA4B,GAAG,IAC7E,CAKA,SAAe+B,2BACbxC,KAAa,CACbyC,QAA4B,4CAMPC,uBAAbC,GAAIC,KAMNtC,MAkBAuC,8FA5BN,GAAIJ,SAASZ,MAAM,GAAK,EAAG,CACzB,YACF,CAEqBa,uBAAAA,sBAAsB1C,MAAOyC,UAA1CE,GAAaD,uBAAbC,GAAIC,KAASF,uBAATE,KACZ,GAAID,GAAGd,MAAM,GAAK,GAAKe,KAAKf,MAAM,GAAK,EAAG,CACxCiB,QAAQC,GAAG,CAAC,gBACZ,YACF,CAEMzC,MAAkB,CACtB,+BACA,GACA,wDACA,AAAC,kCAAuC,OAANN,MAAM,mBACxC,gBALsB,OAMtB,qBAAG2C,KACH,MACA,IACA,GACA,0DACA,AAAC,kCAAuC,OAAN3C,MAAM,mBACxC,cACA,qBAAG4C,OACH,MACA,MAGIC,kBAAoBJ,SACvB7B,GAAG,CAAC,SAACoC,gBAAYA,QAAQ/C,OAAO,CAACiB,IAAI,CAAC,OACtCA,IAAI,CAAC,WAGJlB,MAAAA,MACAS,KAAM,UACNM,MAAO,AAAC,YAAqB8B,OAAV7C,MAAM,MAAsB,OAAlB6C,oBAClB,SAAM7B,iBAAQ,CAACC,MAAM,CAACX,MAAMY,IAAI,CAAC,MAAO,CACjDR,OAAQ,YACV,WAPJ,gBAKIS,UAAW,wBAKjB,KAKA,SAASuB,sBACP1C,KAAa,CACbyC,QAA4B,EAE5B,OAAOA,SAASQ,MAAM,CACpB,SAACC,EAAGF,SACF,IAAMG,mBAAqBH,QAAQ/C,OAAO,CACvCW,GAAG,CAAC,SAAC2B,WAAQ,AAAC,IAAgC,OAA7BA,IAAIa,OAAO,CAAC,AAAC,GAAQ,OAANpD,MAAM,KAAI,IAAI,OAC9CkB,IAAI,CAAC,KACRgC,EAAEP,EAAE,CAACpB,IAAI,CACP,AAAC,kBACkByB,OADDA,QAAQ/C,OAAO,CAACiB,IAAI,CAAC,KAAK,iCAE3B8B,OADEA,QAAQK,EAAE,CAAC,+BAEbL,OADAA,QAAQM,QAAQ,CAAC,+BACA,OAAjBN,QAAQO,QAAQ,CAAC,OAEpCL,EAAEN,IAAI,CAACrB,IAAI,CAAC,AAAC,sBAAwC,OAAnB4B,mBAAmB,OACrD,OAAOD,CACT,EACA,CACEP,GAAI,EAAE,CACNC,KAAM,EAAE,AACV,EAEJ,CAKA,SAAeY,mCACbxD,KAAa,CACbyD,aAAgC,CAChCC,aAA+B,CAC/BC,SAA4B,CAC5BC,SAA2B,CAC3BC,UAA8B,4CAexBC,eAGAC,mBAQAC,eAGkC7D,YAAjCC,aAAcC,gBAMf4D,iBAOA3D,MAsCAa,UAIAJ,6EArEA+C,eAAiBI,kBAAkBT,cAAeE,WAGlDI,mBAAqBI,sBACzBL,eACAL,cACAzD,MACA6D,YAIIG,eAAiBI,kBAAkBV,cAAeE,WAGhBzD,6BAAAA,eAAC,CAACI,SAAS,CACjDyD,eAAeK,GAAG,CAClB,SAAC7D,UAAMA,EAAEC,IAAI,GAAK,YAAcD,EAAEE,MAAM,GAAK,aAFxCN,aAAiCD,eAAnBE,gBAAmBF,eAMlC8D,iBAAmBD,eAAeM,IAAI,CAACC,MAAM,CACjD,SAAC1D,cACCA,MAAMZ,OAAO,CAACuE,KAAK,CAAC,SAACC,gBACnBX,eAAeQ,IAAI,CAAC1D,GAAG,CAAC,SAAC2B,YAAQA,IAAIjB,IAAI,GAAEM,QAAQ,CAAC6C,aAChD,QAGJnE,MAAkB,CACtB,+BACA,GACA,wDACA,AAAC,iCAAsC,OAANN,MAAM,oBAJjB,OAMtB,qBAAI8D,eAAeO,GAAG,CAACxC,MAAM,CAAG,EAAIkC,mBAAmBM,GAAG,CAAC1B,EAAE,KAE7D,qBAAImB,eAAeQ,IAAI,CAACzC,MAAM,CAAG,EAAIkC,mBAAmBO,IAAI,CAAC3B,EAAE,KAE/D,qBAAImB,eAAeY,KAAK,CAAC7C,MAAM,CAAG,EAAIkC,mBAAmBW,KAAK,CAAC/B,EAAE,KAEjE,qBAAGtC,gBAAgBO,GAAG,CAAC,SAACC,cAAUC,mBAAmBD,MAAOb,UAE5D,qBAAGiE,iBAAiBrD,GAAG,CAAC+D,0BACxB,OAEA,qBAAGvE,aAAaQ,GAAG,CAAC,SAACC,cAAUC,mBAAmBD,MAAOb,WACzD,IACA,GACA,0DACA,AAAC,kCAAuC,OAANA,MAAM,oBACxC,qBAAI8D,eAAeO,GAAG,CAACxC,MAAM,CAAG,EAAIkC,mBAAmBM,GAAG,CAACzB,IAAI,KAC/D,qBAAIkB,eAAeQ,IAAI,CAACzC,MAAM,CAAG,EAAIkC,mBAAmBO,IAAI,CAAC1B,IAAI,KACjE,qBAAIkB,eAAeY,KAAK,CAAC7C,MAAM,CAAG,EAAIkC,mBAAmBW,KAAK,CAAC9B,IAAI,KACnE,qBAAGoB,eAAeK,GAAG,CAClBE,MAAM,CACL,SAAC1D,cACCA,MAAMZ,OAAO,CAACuE,KAAK,CAAC,SAACC,gBACnBX,eAAeO,GAAG,CAACzD,GAAG,CAAC,SAAC2B,YAAQA,IAAIjB,IAAI,GAAEM,QAAQ,CAAC6C,aAC/C,QAET7D,GAAG,CAAC+D,yBACP,qBAAGV,iBAAiBrD,GAAG,CAAC,SAACC,cAAUC,mBAAmBD,MAAOb,WAC7D,MACA,MAGgB,SAAMgB,iBAAQ,CAACC,MAAM,CAACX,MAAMY,IAAI,CAAC,MAAO,CACxDR,OAAQ,YACV,WAFMS,UAAY,cAIZJ,MAAQ,CACZ,QACAf,OAFY,OAGZ,qBAAG,CAAE,MAAO,OAAQ,SACjBY,GAAG,CAAC,SAACgE,QACJ,IAAMC,IAAMf,cAAc,CAACc,OAAO,CAAC/C,MAAM,CACzC,GAAIgD,IAAM,EAAG,CACX,OAAOD,OAASC,GAClB,CACA,OAAO,IACT,GACCN,MAAM,CAAC,SAACO,aAASA,OAAS,SAC7B5D,IAAI,CAAC,KAEP,UACE,CACElB,MAAAA,MACAe,MAAAA,MACAI,UAAAA,UACAV,KAAM,QACR,MAEJ,KAKA,SAASyD,kBACPT,aAAgC,CAChCE,SAA4B,EAE5B,IAAMoB,UAAY,CAChBV,IAAK,EAAE,CACPC,KAAM,EAAE,CACRI,MAAO,EAAE,AACX,EAGA,IAAMM,aAAe,CACnBC,GAAI9E,eAAC,CAAC+E,YAAY,CAACvB,UAAWF,cAAe,SAAClB,YAAQA,IAAIjB,IAAI,GAC9D6D,OAAQhF,eAAC,CAAC+E,YAAY,CAACzB,cAAeE,UAAW,SAACpB,YAAQA,IAAIjB,IAAI,EACpE,EACA,GAAI0D,aAAaG,MAAM,CAACtD,MAAM,CAAG,EAAG,CAClCkD,UAAUV,GAAG,CAAGU,UAAUV,GAAG,CAACe,MAAM,CAACJ,aAAaG,MAAM,CAC1D,CACA,GAAIH,aAAaC,EAAE,CAACpD,MAAM,CAAG,EAAG,CAC9BkD,UAAUT,IAAI,CAAGS,UAAUT,IAAI,CAACc,MAAM,CAACJ,aAAaC,EAAE,CACxD,CAGA,IAAMI,cAAgBlF,eAAC,CAACmF,cAAc,CACpC3B,UACAF,cACA,SAAClB,YAAQA,IAAIjB,IAAI,GAEnB,IAAMiE,cAAgBpF,eAAC,CAACmF,cAAc,CACpC7B,cACAE,UACA,SAACpB,YAAQA,IAAIjB,IAAI,EAEnByD,CAAAA,UAAUL,KAAK,CAAGvE,eAAC,CAACqF,cAAc,CAACH,cAAeE,cAAe,SAACE,EAAGC,SACnEC,GAAAA,sBAAK,EAACF,EAAGC,KAGX,OAAOX,SACT,CAKA,SAASZ,sBACPY,SAA+C,CAC/CtB,aAAgC,CAChCzD,KAAa,CACb6D,UAA8B,EAE9B,IAAI+B,QAAU,CACZvB,IAAK,CACH1B,GAAI,EAAE,CACNC,KAAM,EAAE,AACV,EACA0B,KAAM,CACJ3B,GAAI,EAAE,CACNC,KAAM,EAAE,AACV,EACA8B,MAAO,CACL/B,GAAI,EAAE,CACNC,KAAM,EAAE,AACV,CACF,CAEAgD,CAAAA,QAAQvB,GAAG,CAAG,CACZ1B,GAAI,CAAC,SAAiD,CAAlD,OAAW,qBAAGhC,qBAAqBoE,UAAUV,GAAG,IACpDzB,KAAM,CACJ,oBACA,AAAC,qBAEa,OAFOmC,UAAUV,GAAG,CAC/BzD,GAAG,CAAC,SAAC2B,WAAQ,AAAC,IAAY,OAATA,IAAIjB,IAAI,CAAC,OAC1BJ,IAAI,CAAC,MAAM,KACf,AACH,EAGA,IAAM2E,gBAAkBd,UAAUT,IAAI,CAAC1D,GAAG,CAAC,SAAC2B,YAAQA,IAAIjB,IAAI,GAC5D,IAAMwE,qBAAuBjC,WAAWU,MAAM,CAAC,SAACwB,WAC9CA,GAAG9F,OAAO,CAAC+F,IAAI,CAAC,SAACzD,YAAQsD,gBAAgBjE,QAAQ,CAACW,SAGpD,IAAM0D,YAAcH,qBAAqBlF,GAAG,CAAC,SAACmF,IAC5C,IAAM5C,mBAAqB4C,GAAG9F,OAAO,CAACW,GAAG,CAAC,SAAC2B,WAAQ,AAAC,IAAO,OAAJA,IAAI,OAAIrB,IAAI,CAAC,KACpE,MAAO,AAAC,sBAAwC,OAAnBiC,mBAAmB,KAClD,GAEA,IAAM+C,eAAiBxD,sBAAsB1C,MAAO8F,sBAAsBnD,EAAE,AAE5EiD,CAAAA,QAAQtB,IAAI,CAAG,CACb3B,GAAI,AACF,qBAAIsD,YAAYpE,MAAM,CAAG,EACrB,CAAC,gDAAgE,CAAjE,OAAkD,qBAAGoE,cACrD,EAAE,SAHJ,CAIF,kBACA,AAAC,qBAEa,OAFOlB,UAAUT,IAAI,CAChC1D,GAAG,CAAC,SAAC2B,WAAQ,AAAC,IAAY,OAATA,IAAIjB,IAAI,CAAC,OAC1BJ,IAAI,CAAC,MAAM,KACf,EACD0B,KAAM,CACJ,6BAKD,CANK,OAEJ,qBAAGjC,qBAAqBoE,UAAUT,IAAI,GACtC,qBAAI4B,eAAerE,MAAM,CAAG,EACxB,CAAC,0BAA6C,CAA9C,OAA4B,qBAAGqE,iBAC/B,EAAE,EAEV,CACAN,CAAAA,QAAQlB,KAAK,CAAGK,UAAUL,KAAK,CAACzB,MAAM,CACpC,SAACC,EAAGiD,UACF,IAAMC,aAAe3C,cAAc4C,IAAI,CACrC,SAAC9D,YAAQA,IAAIjB,IAAI,EAAI6E,SAAS7E,IAAI,GAEpC,GAAI8E,eAAiBnE,UAAW,CAC9B,OAAOiB,CACT,CAGA,IAAMoD,aAAenG,eAAC,CAACoG,UAAU,CAC/B5F,qBAAqB,CAACyF,aAAa,EACnCzF,qBAAqB,CAACwF,SAAS,GAEjC,IAAMK,eAAiBrG,eAAC,CAACoG,UAAU,CACjC5F,qBAAqB,CAACwF,SAAS,EAC/BxF,qBAAqB,CAACyF,aAAa,GAErC,GAAIE,aAAazE,MAAM,CAAG,EAAG,CAC3BqB,EAAEP,EAAE,CAAG,AACL,qBAAGO,EAAEP,EAAE,SADF,CAEL,kBAED,CADC,qBAAG2D,aAAa1F,GAAG,CAAC,SAAC6F,UAAMA,EAAErD,OAAO,CAAC,IAAK,IAAM,eAElDF,CAAAA,EAAEN,IAAI,CAAG,AACP,qBAAGM,EAAEN,IAAI,SADF,CAEP,6BAED,CADC,qBAAG4D,eAAe5F,GAAG,CAAC,SAAC6F,UAAMA,EAAErD,OAAO,CAAC,IAAK,IAAM,eAEtD,CAEA,OAAOF,CACT,EACA,CACEP,GAAI,EAAE,CACNC,KAAM,EAAE,AACV,GAGF,OAAOgD,OACT,CAKA,SAASxB,kBACPV,aAA+B,CAC/BE,SAA2B,EAG3B,IAAI8C,UAAY,CACdrC,IAAK,EAAE,CACPC,KAAM,EAAE,AACV,EACA,IAAMqC,aAAe,CACnB1B,GAAI9E,eAAC,CAAC+E,YAAY,CAACtB,UAAWF,cAAe,SAACnB,WAC5C,CAACA,IAAI9B,IAAI,CAAE8B,IAAItC,OAAO,CAACiB,IAAI,CAAC,KAAK,CAACA,IAAI,CAAC,QAEzCiE,OAAQhF,eAAC,CAAC+E,YAAY,CAACxB,cAAeE,UAAW,SAACrB,WAChD,CAACA,IAAI9B,IAAI,CAAE8B,IAAItC,OAAO,CAACiB,IAAI,CAAC,KAAK,CAACA,IAAI,CAAC,OAE3C,EACA,GAAIyF,aAAaxB,MAAM,CAACtD,MAAM,CAAG,EAAG,CAClC6E,UAAUrC,GAAG,CAAGqC,UAAUrC,GAAG,CAACe,MAAM,CAACuB,aAAaxB,MAAM,CAC1D,CACA,GAAIwB,aAAa1B,EAAE,CAACpD,MAAM,CAAG,EAAG,CAC9B6E,UAAUpC,IAAI,CAAGoC,UAAUpC,IAAI,CAACc,MAAM,CAACuB,aAAa1B,EAAE,CACxD,CAEA,OAAOyB,SACT,CAKA,SAAS/B,uBAAuB9D,KAAqB,EACnD,IAAMsB,UAAY,CAChBtB,MAAO,QACPuB,SAAU,QACVC,OAAQ,QACV,EAEA,MAAO,AAAC,aAAsCxB,OAA1BsB,SAAS,CAACtB,MAAMJ,IAAI,CAAC,CAAC,MAE7B,OAFiCI,MAAMZ,OAAO,CACxDW,GAAG,CAAC,SAACgG,kBAAe,AAAC,IAAc,OAAXA,WAAW,OACnC1F,IAAI,CAAC,KAAK,KACf,CAKA,SAAe2F,yEACb7G,KAAa,CACb8G,cAAkC,CAClCjD,UAA8B,MAC9BkD,gBAIMC,OAKAC,oBAEAC,KA2CAtB,QAQAuB,SAOA7G,MAsBAa,UAIAJ,sGA/FNgG,gBAAAA,6DAIMC,OAAS,SAACI,IACd,MAAO,CAACA,GAAGnH,OAAO,CAACiB,IAAI,CAAC,KAAMkG,GAAG/D,EAAE,CAAC,CAACnC,IAAI,CAAC,MAC5C,EAGM+F,oBAAsBF,gBAAgBnG,GAAG,CAAC,SAAC2B,YAAQA,IAAIjB,IAAI,GAE3D4F,KAAOJ,eAAe7D,MAAM,CAChC,SAACoE,OAAQC,SACP,IAAMC,YAAc1D,WAAWwC,IAAI,CACjC,SAACmB,YAAQR,OAAOM,WAAaN,OAAOQ,OAEtC,GAAI,CAACD,YAAa,CAChBF,OAAOhD,GAAG,CAAC9C,IAAI,CAAC+F,SAChB,OAAOD,MACT,CAEA,GAAI1B,GAAAA,sBAAK,EAAC2B,QAASC,eAAiB,MAAO,CACzCF,OAAOI,QAAQ,CAAClG,IAAI,CAACgG,aACrBF,OAAOK,QAAQ,CAACnG,IAAI,CAAC+F,SACrB,OAAOD,MACT,CACA,OAAOA,MACT,EACA,CACEhD,GAAG,IACHC,IAAI,IACJmD,QAAQ,IACRC,QAAQ,GACV,GAKF7D,WAAW8D,OAAO,CAAC,SAACH,KAClB,IAAMI,gBAAkBd,eAAeT,IAAI,CACzC,SAACiB,gBAAYN,OAAOM,WAAaN,OAAOQ,OAE1C,GAAI,CAACI,gBAAiB,CAEpB,IAAMC,iBAAmBL,IAAIvH,OAAO,CAAC+F,IAAI,CAAC,SAACzD,YACzC0E,oBAAoBrF,QAAQ,CAACW,OAG/B,GAAI,CAACsF,iBAAkB,CACrBX,KAAK5C,IAAI,CAAC/C,IAAI,CAACiG,IACjB,CACF,CACF,GAEM5B,QAAU,CACdvB,IAAK3B,sBAAsB1C,MAAOkH,KAAK7C,GAAG,EAC1CC,KAAM5B,sBAAsB1C,MAAOkH,KAAK5C,IAAI,EAC5CmD,SAAU/E,sBAAsB1C,MAAOkH,KAAKO,QAAQ,EACpDC,SAAUhF,sBAAsB1C,MAAOkH,KAAKQ,QAAQ,CACtD,EAGMP,SAAWW,OAAOC,MAAM,CAACnC,SAASI,IAAI,CAC1C,SAACS,UAAMA,EAAE9D,EAAE,CAACd,MAAM,CAAG,GAAK4E,EAAE7D,IAAI,CAACf,MAAM,CAAG,IAE5C,GAAI,CAACsF,SAAU,CACb,YACF,CAEM7G,MAAkB,CACtB,+BACA,GACA,wDACA,AAAC,kCAAuC,OAANN,MAAM,oBAJlB,OAKtB,qBAAG4F,QAAQtB,IAAI,CAAC1B,IAAI,EACpB,qBAAGgD,QAAQvB,GAAG,CAAC1B,EAAE,EACjB,qBAAGiD,QAAQ6B,QAAQ,CAAC7E,IAAI,EACxB,qBAAGgD,QAAQ8B,QAAQ,CAAC/E,EAAE,GACtB,KACA,IACA,GACA,0DACA,AAAC,kCAAuC,OAAN3C,MAAM,oBACxC,qBAAG4F,QAAQvB,GAAG,CAACzB,IAAI,EACnB,qBAAGgD,QAAQ8B,QAAQ,CAAC9E,IAAI,EACxB,qBAAGgD,QAAQ6B,QAAQ,CAAC9E,EAAE,EACtB,qBAAGiD,QAAQtB,IAAI,CAAC3B,EAAE,GAClB,KACA,MAGgB,SAAM3B,iBAAQ,CAACC,MAAM,CAACX,MAAMY,IAAI,CAAC,MAAO,CACxDR,OAAQ,YACV,WAFMS,UAAY,cAIZJ,MAAQ,CACZ,QACAf,MACA,YAEAkB,IAAI,CAAC,KAEP,UACE,CACElB,MAAAA,MACAe,MAAAA,MACAI,UAAAA,UACAV,KAAM,QACR,MAEJ,yBAOO,SAAeX,mBACpBkI,SAAuB,wHAGrB,SAAMjI,oCACJiI,UAAUhI,KAAK,CACfgI,UAAU/H,OAAO,CACjB+H,UAAU9H,OAAO,iBAHnB,gBADK,OAMD,SAAMsC,2BAA2BwF,UAAUhI,KAAK,CAAEgI,UAAUvF,QAAQ,UAN1E,SAAO,YAML,mCAAI,qBAER,KAQO,SAAe5C,kBACpBmI,SAAuB,CACvBC,KAAmB,4CAEbC,uBAwBAzE,cAGAE,UAcAD,cAGAE,UAIAuE,uBAUArB,eAGAjD,WAKAkD,gBAMAqB,WAGAC,eACAC,2FA5EAJ,uBAAyB,SAAC3F,KAE9B,GACEA,IAAI9B,IAAI,GAAK,SACb8B,IAAIP,SAAS,EACbuG,OAAOhG,IAAIP,SAAS,EAAEJ,QAAQ,CAAC,OAAS,MACxC,KACkDW,UAAlDA,CAAAA,IAAIP,SAAS,CAAG,AAAC,IAAiD,OAA9CwG,OAAOjG,IAAIP,SAAS,EAAEyG,OAAO,CAAClG,CAAAA,WAAAA,IAAId,KAAK,UAATc,oBAAAA,WAAa,GAAG,IACpE,CAEA,GAAIA,IAAI9B,IAAI,GAAK,UAAY8B,IAAIP,SAAS,GAAK,GAAI,CACjDO,IAAIP,SAAS,CAAG,IAClB,CAGA,GAAIO,IAAI9B,IAAI,GAAK,WAAa8B,IAAIP,SAAS,GAAKC,UAAW,CACzD,GAAIM,IAAIP,SAAS,GAAK,KAAOO,IAAIP,SAAS,CAAC0G,WAAW,KAAO,QAAS,CACpEnG,IAAIP,SAAS,CAAG,GAClB,MAAO,GAAIO,IAAIP,SAAS,GAAK,KAAOO,IAAIP,SAAS,CAAC0G,WAAW,KAAO,OAAQ,CAC1EnG,IAAIP,SAAS,CAAG,GAClB,CACF,CACA,OAAOO,GACT,EACMkB,cAAgBtD,eAAC,CAACwI,MAAM,CAACX,UAAU/H,OAAO,CAAE,SAACwF,UAAMA,EAAEnE,IAAI,GAAEV,GAAG,CAClEsH,wBAEIvE,UAAYxD,eAAC,CAACwI,MAAM,CAACV,MAAMhI,OAAO,CAAE,SAACwF,UAAMA,EAAEnE,IAAI,GAAEV,GAAG,CAC1DsH,wBAaIxE,cAAgBvD,eAAC,CAACwI,MAAM,CAACX,UAAU9H,OAAO,CAAE,SAACuF,SACjD,CAACA,EAAEhF,IAAI,CAAoD,CAA3D,OAAS,qBAAGgF,EAAExF,OAAO,CAAC2I,IAAI,CAAC,SAACC,GAAIC,WAAQD,GAAKC,GAAK,EAAI,CAAC,MAAK5H,IAAI,CAAC,OAE7D0C,UAAYzD,eAAC,CAACwI,MAAM,CAACV,MAAM/H,OAAO,CAAE,SAACuF,SACzC,CAACA,EAAEhF,IAAI,CAAoD,CAA3D,OAAS,qBAAGgF,EAAExF,OAAO,CAAC2I,IAAI,CAAC,SAACC,GAAIC,WAAQD,GAAKC,GAAK,EAAI,CAAC,MAAK5H,IAAI,CAAC,OAG7DiH,uBAAyB,SAACY,GAE9B,IAAQxF,SAAuBwF,EAAvBxF,SAAUD,SAAayF,EAAbzF,SAClB,OAAO,uCACFyF,IACHzF,SAAUA,WAAa,WAAa,YAAcA,SAClDC,SAAUA,WAAa,WAAa,YAAcA,UAEtD,EAEMuD,eAAiB3G,eAAC,CAACwI,MAAM,CAACX,UAAUvF,QAAQ,CAAE,SAACgD,SACnD,CAACA,EAAEpC,EAAE,CAAe,CAApB,OAAO,qBAAGoC,EAAExF,OAAO,GAAEiB,IAAI,CAAC,OAC1BN,GAAG,CAAC,SAACmI,UAAMZ,uBAAuBY,KAC9BlF,WAAa1D,eAAC,CAACwI,MAAM,CAACV,MAAMxF,QAAQ,CAAE,SAACgD,SAC3C,CAACA,EAAEpC,EAAE,CAAe,CAApB,OAAO,qBAAGoC,EAAExF,OAAO,GAAEiB,IAAI,CAAC,OAC1BN,GAAG,CAAC,SAACmI,UAAMZ,uBAAuBY,KAG9BhC,gBAAkB5G,eAAC,CAAC+E,YAAY,CACpCvB,UACAF,cACA,SAAClB,YAAQA,IAAIjB,IAAI,GAGb8G,cAGAC,eAAiB1C,GAAAA,sBAAK,EAAClC,cAAeE,WACtC2E,eAAiB3C,GAAAA,sBAAK,EAC1BjC,cAAc9C,GAAG,CAAC,SAACC,cAAUV,eAAC,CAAC6I,IAAI,CAACnI,MAAO,CAAC,SAAS,IACrD+C,eAEE,CAAA,CAACyE,gBAAkB,CAACC,cAAa,EAAjC,cACFF,WAAW7G,IAAI,CACb,SAAMiC,mCACJwE,UAAUhI,KAAK,CACfyD,cACAC,cACAC,UACAC,UACAqE,MAAMxF,QAAQ,UAPlB2F,QAAAA,YACE,0CAYAzC,CAAAA,GAAAA,sBAAK,EAACmB,eAAgBjD,cAAgB,KAAI,EAA1C8B,eACFyC,WAAW7G,IAAI,CACb,SAAMsF,2BACJmB,UAAUhI,KAAK,CACf8G,eACAjD,WACAkD,yBALJqB,SAAAA,YACE,sCASJ,GAAIA,WAAW5D,KAAK,CAAC,SAACyE,kBAAcA,YAAc,OAAO,CACvD,YACF,CAEA,SAAOb,WAAW7D,MAAM,CAAC,SAAC0E,kBAAcA,YAAc,OAAMC,IAAI,MAClE"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/migration/migration-set.ts"],"sourcesContent":["import { Knex } from \"knex\";\nimport { DBColumn, DBForeign, DBIndex } from \"./types\";\nimport _ from \"lodash\";\nimport inflection from \"inflection\";\nimport { Entity } from \"../entity/entity\";\nimport { EntityManager } from \"../entity/entity-manager\";\nimport {\n isKnexError,\n MigrationSet,\n RelationOn,\n isBelongsToOneRelationProp,\n isDecimalProp,\n isEnumProp,\n isFloatProp,\n isHasManyRelationProp,\n isIntegerProp,\n isManyToManyRelationProp,\n isOneToOneRelationProp,\n isRelationProp,\n isStringProp,\n isTextProp,\n isVirtualProp,\n KnexColumnType,\n MigrationColumn,\n MigrationForeign,\n MigrationIndex,\n MigrationJoinTable,\n MigrationSetAndJoinTable,\n} from \"../types/types\";\n\n/**\n * DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.\n * @param compareDB Knex 인스턴스\n * @param table 테이블 이름\n * @returns MigrationSet 객체\n */\nexport async function getMigrationSetFromDB(\n compareDB: Knex,\n table: string\n): Promise<MigrationSet | null> {\n let dbColumns: DBColumn[], dbIndexes: DBIndex[], dbForeigns: DBForeign[];\n try {\n [dbColumns, dbIndexes, dbForeigns] = await readTable(compareDB, table);\n } catch (e: unknown) {\n if (isKnexError(e) && e.code === \"ER_NO_SUCH_TABLE\") {\n return null;\n }\n console.error(e);\n return null;\n }\n\n const columns: MigrationColumn[] = dbColumns.map((dbColumn) => {\n const dbColType = resolveDBColType(dbColumn.Type, dbColumn.Field);\n return {\n name: dbColumn.Field,\n nullable: dbColumn.Null !== \"NO\",\n ...dbColType,\n ...(() => {\n if (dbColumn.Default !== null) {\n return {\n defaultTo: dbColumn.Default,\n };\n }\n return {};\n })(),\n };\n });\n\n const dbIndexesGroup = _.groupBy(\n dbIndexes.filter(\n (dbIndex) =>\n dbIndex.Key_name !== \"PRIMARY\" &&\n !dbForeigns.find((dbForeign) => dbForeign.keyName === dbIndex.Key_name)\n ),\n (dbIndex) => dbIndex.Key_name\n );\n\n const parseIndexType = (index: DBIndex) => {\n if (index.Index_type === \"FULLTEXT\") {\n return \"fulltext\";\n }\n return index.Non_unique === 1 ? \"index\" : \"unique\";\n };\n\n // indexes 처리\n const indexes: MigrationIndex[] = Object.keys(dbIndexesGroup).map(\n (keyName) => {\n const currentIndexes = dbIndexesGroup[keyName];\n return {\n type: parseIndexType(currentIndexes[0]),\n columns: currentIndexes.map((currentIndex) => currentIndex.Column_name),\n };\n }\n );\n // console.log(table);\n // console.table(dbIndexes);\n // console.table(dbForeigns);\n\n // foreigns 처리\n const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {\n return {\n columns: [dbForeign.from],\n to: `${dbForeign.referencesTable}.${dbForeign.referencesField}`,\n onUpdate: dbForeign.onUpdate as RelationOn,\n onDelete: dbForeign.onDelete as RelationOn,\n };\n });\n\n return {\n table,\n columns,\n indexes,\n foreigns,\n };\n}\n\n/*\n * 기존 테이블 읽어서 cols, indexes 반환\n */\nasync function readTable(\n compareDB: Knex,\n tableName: string\n): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {\n // 테이블 정보\n try {\n const [_cols] = (await compareDB.raw(`SHOW FIELDS FROM ${tableName}`)) as [\n DBColumn[],\n ];\n const cols = _cols.map((col) => ({\n ...col,\n // Default 값은 숫자나 MySQL Expression이 아닌 경우 \"\"로 감싸줌\n ...(col.Default !== null && {\n Default:\n col.Default.replace(/[0-9]+/g, \"\").length > 0 &&\n col.Extra !== \"DEFAULT_GENERATED\"\n ? `\"${col.Default}\"`\n : col.Default,\n }),\n }));\n\n const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);\n const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);\n const ddl = row[\"Create Table\"];\n const matched = ddl.match(/CONSTRAINT .+/g);\n const foreignKeys = (matched ?? []).map((line: string) => {\n // 해당 라인을 정규식으로 파싱\n const matched = line.match(\n /CONSTRAINT `(.+)` FOREIGN KEY \\(`(.+)`\\) REFERENCES `(.+)` \\(`(.+)`\\)( ON [A-Z ]+)*/\n );\n if (!matched) {\n throw new Error(`인식할 수 없는 FOREIGN KEY CONSTRAINT ${line}`);\n }\n const [, keyName, from, referencesTable, referencesField, onClause] =\n matched;\n // console.debug({ tableName, line, onClause });\n\n const [onUpdateFull, _onUpdate] =\n (onClause ?? \"\").match(/ON UPDATE ([A-Z ]+)$/) ?? [];\n const onUpdate = _onUpdate ?? \"NO ACTION\";\n\n const onDelete =\n (onClause ?? \"\")\n .replace(onUpdateFull ?? \"\", \"\")\n .match(/ON DELETE ([A-Z ]+)/)?.[1]\n ?.trim() ?? \"NO ACTION\";\n\n return {\n keyName,\n from,\n referencesTable,\n referencesField,\n onDelete,\n onUpdate,\n };\n });\n return [cols, indexes, foreignKeys];\n } catch (e) {\n throw e;\n }\n}\n\nfunction resolveDBColType(\n colType: string,\n colField: string\n): Pick<\n MigrationColumn,\n \"type\" | \"unsigned\" | \"length\" | \"precision\" | \"scale\"\n> {\n let [rawType, unsigned] = colType.split(\" \");\n const matched = rawType.match(/\\(([0-9]+)\\)/);\n let length;\n if (matched !== null && matched[1]) {\n rawType = rawType.replace(/\\(([0-9]+)\\)/, \"\");\n length = parseInt(matched[1]);\n }\n\n if (rawType === \"char\" && colField === \"uuid\") {\n return {\n type: \"uuid\",\n };\n }\n\n switch (rawType) {\n case \"int\":\n return {\n type: \"integer\",\n unsigned: unsigned === \"unsigned\",\n };\n case \"varchar\":\n // case \"char\":\n return {\n type: \"string\",\n ...(length !== undefined && {\n length,\n }),\n };\n case \"text\":\n case \"mediumtext\":\n case \"longtext\":\n case \"timestamp\":\n case \"json\":\n case \"date\":\n case \"time\":\n return {\n type: rawType,\n };\n case \"datetime\":\n return {\n type: \"datetime\",\n };\n case \"tinyint\":\n return {\n type: \"boolean\",\n };\n default:\n // decimal 처리\n if (rawType.startsWith(\"decimal\")) {\n const [, precision, scale] =\n rawType.match(/decimal\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"decimal\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n } else if (rawType.startsWith(\"float\")) {\n const [, precision, scale] =\n rawType.match(/float\\(([0-9]+),([0-9]+)\\)/) ?? [];\n return {\n type: \"float\",\n precision: parseInt(precision),\n scale: parseInt(scale),\n ...(unsigned === \"unsigned\" && {\n unsigned: true,\n }),\n };\n }\n throw new Error(`resolve 불가능한 DB컬럼 타입 ${colType} ${rawType}`);\n }\n}\n\n/**\n * Entity를 읽어서 MigrationSetAndJoinTable을 만들어옵니다.\n * @param entity Entity 객체\n * @returns MigrationSetAndJoinTable 객체\n */\nexport function getMigrationSetFromEntity(\n entity: Entity\n): MigrationSetAndJoinTable {\n const migrationSet: MigrationSetAndJoinTable = entity.props.reduce(\n (r, prop) => {\n // virtual 필드 제외\n if (isVirtualProp(prop)) {\n return r;\n }\n // HasMany 케이스는 아무 처리도 하지 않음\n if (isHasManyRelationProp(prop)) {\n return r;\n }\n\n // 일반 컬럼\n if (!isRelationProp(prop)) {\n // type resolve\n let type: KnexColumnType;\n if (isTextProp(prop)) {\n type = prop.textType;\n } else if (isEnumProp(prop)) {\n type = \"string\";\n } else {\n type = prop.type as KnexColumnType;\n }\n\n const column = {\n name: prop.name,\n type,\n ...(isIntegerProp(prop) && { unsigned: prop.unsigned === true }),\n ...((isStringProp(prop) || isEnumProp(prop)) && {\n length: prop.length,\n }),\n nullable: prop.nullable === true,\n ...(() => {\n if (prop.dbDefault !== undefined) {\n return {\n defaultTo: prop.dbDefault,\n };\n }\n return {};\n })(),\n // FIXME: float(N, M) deprecated\n // Decimal, Float 타입의 경우 precision, scale 추가\n ...((isDecimalProp(prop) || isFloatProp(prop)) && {\n precision: prop.precision ?? 8,\n scale: prop.scale ?? 2,\n }),\n };\n\n r.columns.push(column);\n }\n\n if (isManyToManyRelationProp(prop)) {\n // ManyToMany 케이스\n const relMd = EntityManager.get(prop.with);\n const table1 = entity.table;\n const table2 = relMd.table;\n const join = {\n from: `${entity.table}.id`,\n through: {\n from: `${prop.joinTable}.${inflection.singularize(table1)}_id`,\n to: `${prop.joinTable}.${inflection.singularize(table2)}_id`,\n onUpdate: prop.onUpdate,\n onDelete: prop.onDelete,\n },\n to: `${relMd.table}.id`,\n };\n const through = join.through;\n const fields = [through.from, through.to];\n r.joinTables.push({\n table: through.from.split(\".\")[0],\n indexes: [\n {\n type: \"unique\",\n columns: [\"uuid\"],\n },\n // 조인 테이블에 걸린 인덱스 찾아와서 연결\n ...entity.indexes\n .filter((index) =>\n index.columns.find((col) => col.includes(prop.joinTable + \".\"))\n )\n .map((index) => ({\n ...index,\n columns: index.columns.map((col) =>\n col.replace(prop.joinTable + \".\", \"\")\n ),\n })),\n ],\n columns: [\n {\n name: \"id\",\n type: \"integer\",\n nullable: false,\n unsigned: true,\n },\n ...fields.map((field) => {\n return {\n name: field.split(\".\")[1],\n type: \"integer\",\n nullable: false,\n unsigned: true,\n } as MigrationColumn;\n }),\n {\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n },\n ],\n foreigns: fields.map((field) => {\n // 현재 필드가 어떤 테이블에 속하는지 판단\n const col = field.split(\".\")[1];\n const to = (() => {\n if (\n inflection.singularize(join.to.split(\".\")[0]) + \"_id\" ===\n col\n ) {\n return join.to;\n } else {\n return join.from;\n }\n })();\n return {\n columns: [col],\n to,\n onUpdate: through.onUpdate,\n onDelete: through.onDelete,\n };\n }),\n });\n return r;\n } else if (\n isBelongsToOneRelationProp(prop) ||\n (isOneToOneRelationProp(prop) && prop.hasJoinColumn)\n ) {\n // -OneRelation 케이스\n const idColumnName = prop.name + \"_id\";\n r.columns.push({\n name: idColumnName,\n type: \"integer\",\n unsigned: true,\n nullable: prop.nullable ?? false,\n });\n if ((prop.useConstraint ?? true) === true) {\n r.foreigns.push({\n columns: [idColumnName],\n to: `${inflection\n .underscore(inflection.pluralize(prop.with))\n .toLowerCase()}.id`,\n onUpdate: prop.onUpdate ?? \"RESTRICT\",\n onDelete: prop.onDelete ?? \"RESTRICT\",\n });\n }\n }\n\n return r;\n },\n {\n table: entity.table,\n columns: [] as MigrationColumn[],\n indexes: [] as MigrationIndex[],\n foreigns: [] as MigrationForeign[],\n joinTables: [] as MigrationJoinTable[],\n }\n );\n\n // indexes\n migrationSet.indexes = entity.indexes.filter((index) =>\n index.columns.find((col) => col.includes(\".\") === false)\n );\n\n // uuid\n migrationSet.columns = migrationSet.columns.concat({\n name: \"uuid\",\n nullable: true,\n type: \"uuid\",\n } as MigrationColumn);\n migrationSet.indexes = migrationSet.indexes.concat({\n type: \"unique\",\n columns: [\"uuid\"],\n } as MigrationIndex);\n\n return migrationSet;\n}\n"],"names":["getMigrationSetFromDB","getMigrationSetFromEntity","compareDB","table","dbColumns","dbIndexes","dbForeigns","e","columns","dbIndexesGroup","parseIndexType","indexes","foreigns","readTable","isKnexError","code","console","error","map","dbColumn","dbColType","resolveDBColType","Type","Field","name","nullable","Null","Default","defaultTo","_","groupBy","filter","dbIndex","Key_name","find","dbForeign","keyName","index","Index_type","Non_unique","Object","keys","currentIndexes","type","currentIndex","Column_name","from","to","referencesTable","referencesField","onUpdate","onDelete","tableName","_cols","cols","row","ddl","matched","foreignKeys","raw","col","replace","length","Extra","match","line","Error","onClause","onUpdateFull","_onUpdate","trim","colType","colField","split","rawType","unsigned","parseInt","undefined","startsWith","precision","scale","entity","migrationSet","props","reduce","r","prop","isVirtualProp","isHasManyRelationProp","isRelationProp","isTextProp","textType","isEnumProp","column","isIntegerProp","isStringProp","dbDefault","isDecimalProp","isFloatProp","push","isManyToManyRelationProp","relMd","EntityManager","get","with","table1","table2","join","through","inflection","joinTable","singularize","fields","joinTables","includes","field","isBelongsToOneRelationProp","isOneToOneRelationProp","hasJoinColumn","idColumnName","useConstraint","underscore","pluralize","toLowerCase","concat"],"mappings":"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"}