sonamu 0.4.13 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (371) hide show
  1. package/.swcrc +15 -0
  2. package/dist/api/base-frame.d.ts +8 -0
  3. package/dist/api/base-frame.d.ts.map +1 -0
  4. package/dist/api/base-frame.js +2 -0
  5. package/dist/api/base-frame.js.map +1 -0
  6. package/dist/api/caster.d.ts +5 -0
  7. package/dist/api/caster.d.ts.map +1 -0
  8. package/dist/api/caster.js +2 -0
  9. package/dist/api/caster.js.map +1 -0
  10. package/dist/api/code-converters.d.ts +23 -0
  11. package/dist/api/code-converters.d.ts.map +1 -0
  12. package/dist/api/code-converters.js +2 -0
  13. package/dist/api/code-converters.js.map +1 -0
  14. package/dist/api/context.d.ts +16 -0
  15. package/dist/api/context.d.ts.map +1 -0
  16. package/dist/api/context.js +2 -0
  17. package/dist/api/context.js.map +1 -0
  18. package/dist/api/decorators.d.ts +50 -0
  19. package/dist/api/decorators.d.ts.map +1 -0
  20. package/dist/api/decorators.js +2 -0
  21. package/dist/api/decorators.js.map +1 -0
  22. package/dist/api/index.d.ts +8 -0
  23. package/dist/api/index.d.ts.map +1 -0
  24. package/dist/api/index.js +2 -0
  25. package/dist/api/index.js.map +1 -0
  26. package/dist/api/sonamu.d.ts +83 -0
  27. package/dist/api/sonamu.d.ts.map +1 -0
  28. package/dist/api/sonamu.js +2 -0
  29. package/dist/api/sonamu.js.map +1 -0
  30. package/dist/api/sonamu.types.d.ts +30 -0
  31. package/dist/api/sonamu.types.d.ts.map +1 -0
  32. package/dist/api/sonamu.types.js +2 -0
  33. package/dist/api/sonamu.types.js.map +1 -0
  34. package/dist/bin/build-config.d.ts +5 -0
  35. package/dist/bin/build-config.d.ts.map +1 -0
  36. package/dist/bin/build-config.js +2 -0
  37. package/dist/bin/build-config.js.map +1 -0
  38. package/dist/bin/cli-wrapper.d.ts +2 -0
  39. package/dist/bin/cli-wrapper.d.ts.map +1 -0
  40. package/dist/bin/cli-wrapper.js +1 -38
  41. package/dist/bin/cli-wrapper.js.map +1 -1
  42. package/dist/bin/cli.d.ts +2 -2
  43. package/dist/bin/cli.d.ts.map +1 -0
  44. package/dist/bin/cli.js +1 -903
  45. package/dist/bin/cli.js.map +1 -1
  46. package/dist/bin/cli.mjs +2 -2
  47. package/dist/{chunk-DMJSNO2L.js → chunk-2WAC2GER.js} +44 -44
  48. package/dist/{chunk-DMJSNO2L.js.map → chunk-2WAC2GER.js.map} +1 -1
  49. package/dist/{chunk-NI37CY4T.mjs → chunk-C3IPIF6O.mjs} +2 -2
  50. package/dist/{chunk-DYFCACHD.js → chunk-EXHKSVTE.js} +7 -7
  51. package/dist/{chunk-QJFHDCBN.mjs → chunk-FCERKIIF.mjs} +2 -2
  52. package/dist/chunk-FCERKIIF.mjs.map +1 -0
  53. package/dist/{chunk-DDJ7T4MA.mjs → chunk-HGIBJYOU.mjs} +2 -2
  54. package/dist/{chunk-NIFOTHBW.mjs → chunk-JKSOJRQA.mjs} +2 -2
  55. package/dist/{chunk-CXAVBVKC.js → chunk-OTKKFP3Y.js} +100 -100
  56. package/dist/{chunk-J6S43O7G.js → chunk-UZ2IY5VE.js} +4 -4
  57. package/dist/database/_batch_update.d.ts +15 -0
  58. package/dist/database/_batch_update.d.ts.map +1 -0
  59. package/dist/database/_batch_update.js +2 -0
  60. package/dist/database/_batch_update.js.map +1 -0
  61. package/dist/database/base-model.d.ts +41 -0
  62. package/dist/database/base-model.d.ts.map +1 -0
  63. package/dist/database/base-model.js +2 -0
  64. package/dist/database/base-model.js.map +1 -0
  65. package/dist/database/code-generator.d.ts +13 -0
  66. package/dist/database/code-generator.d.ts.map +1 -0
  67. package/dist/database/code-generator.js +2 -0
  68. package/dist/database/code-generator.js.map +1 -0
  69. package/dist/database/db.d.ts +40 -0
  70. package/dist/database/db.d.ts.map +1 -0
  71. package/dist/database/db.js +2 -0
  72. package/dist/database/db.js.map +1 -0
  73. package/dist/database/drivers/knex/base-model.js +8 -8
  74. package/dist/database/drivers/knex/base-model.mjs +3 -3
  75. package/dist/database/drivers/kysely/base-model.js +9 -9
  76. package/dist/database/drivers/kysely/base-model.mjs +3 -3
  77. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +2 -0
  78. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +1 -0
  79. package/dist/database/knex-plugins/knex-on-duplicate-update.js +2 -0
  80. package/dist/database/knex-plugins/knex-on-duplicate-update.js.map +1 -0
  81. package/dist/database/puri-wrapper.d.ts +34 -0
  82. package/dist/database/puri-wrapper.d.ts.map +1 -0
  83. package/dist/database/puri-wrapper.js +2 -0
  84. package/dist/database/puri-wrapper.js.map +1 -0
  85. package/dist/database/puri.d.ts +83 -0
  86. package/dist/database/puri.d.ts.map +1 -0
  87. package/dist/database/puri.js +2 -0
  88. package/dist/database/puri.js.map +1 -0
  89. package/dist/database/puri.types.d.ts +60 -0
  90. package/dist/database/puri.types.d.ts.map +1 -0
  91. package/dist/database/puri.types.js +2 -0
  92. package/dist/database/puri.types.js.map +1 -0
  93. package/dist/database/transaction-context.d.ts +9 -0
  94. package/dist/database/transaction-context.d.ts.map +1 -0
  95. package/dist/database/transaction-context.js +2 -0
  96. package/dist/database/transaction-context.js.map +1 -0
  97. package/dist/database/types.d.ts +39 -0
  98. package/dist/database/types.d.ts.map +1 -0
  99. package/dist/database/types.js +2 -0
  100. package/dist/database/types.js.map +1 -0
  101. package/dist/database/upsert-builder.d.ts +34 -0
  102. package/dist/database/upsert-builder.d.ts.map +1 -0
  103. package/dist/database/upsert-builder.js +2 -0
  104. package/dist/database/upsert-builder.js.map +1 -0
  105. package/dist/entity/entity-manager.d.ts +32 -0
  106. package/dist/entity/entity-manager.d.ts.map +1 -0
  107. package/dist/entity/entity-manager.js +2 -0
  108. package/dist/entity/entity-manager.js.map +1 -0
  109. package/dist/entity/entity-utils.d.ts +61 -0
  110. package/dist/entity/entity-utils.d.ts.map +1 -0
  111. package/dist/entity/entity-utils.js +2 -0
  112. package/dist/entity/entity-utils.js.map +1 -0
  113. package/dist/entity/entity.d.ts +62 -0
  114. package/dist/entity/entity.d.ts.map +1 -0
  115. package/dist/entity/entity.js +2 -0
  116. package/dist/entity/entity.js.map +1 -0
  117. package/dist/entity/migrator.d.ts +135 -0
  118. package/dist/entity/migrator.d.ts.map +1 -0
  119. package/dist/entity/migrator.js +2 -0
  120. package/dist/entity/migrator.js.map +1 -0
  121. package/dist/exceptions/error-handler.d.ts +3 -0
  122. package/dist/exceptions/error-handler.d.ts.map +1 -0
  123. package/dist/exceptions/error-handler.js +2 -0
  124. package/dist/exceptions/error-handler.js.map +1 -0
  125. package/dist/exceptions/so-exceptions.d.ts +48 -0
  126. package/dist/exceptions/so-exceptions.d.ts.map +1 -0
  127. package/dist/exceptions/so-exceptions.js +2 -0
  128. package/dist/exceptions/so-exceptions.js.map +1 -0
  129. package/dist/file-storage/driver.d.ts +45 -0
  130. package/dist/file-storage/driver.d.ts.map +1 -0
  131. package/dist/file-storage/driver.js +2 -0
  132. package/dist/file-storage/driver.js.map +1 -0
  133. package/dist/file-storage/file-storage.d.ts +50 -0
  134. package/dist/file-storage/file-storage.d.ts.map +1 -0
  135. package/dist/file-storage/file-storage.js +2 -0
  136. package/dist/file-storage/file-storage.js.map +1 -0
  137. package/dist/index.d.ts +22 -813
  138. package/dist/index.d.ts.map +1 -0
  139. package/dist/index.js +1 -433
  140. package/dist/index.js.map +1 -1
  141. package/dist/index.mjs +3 -3
  142. package/dist/migration/code-generation.d.ts +15 -0
  143. package/dist/migration/code-generation.d.ts.map +1 -0
  144. package/dist/migration/code-generation.js +2 -0
  145. package/dist/migration/code-generation.js.map +1 -0
  146. package/dist/migration/migration-set.d.ts +17 -0
  147. package/dist/migration/migration-set.d.ts.map +1 -0
  148. package/dist/migration/migration-set.js +2 -0
  149. package/dist/migration/migration-set.js.map +1 -0
  150. package/dist/migration/migrator.d.ts +130 -0
  151. package/dist/migration/migrator.d.ts.map +1 -0
  152. package/dist/migration/migrator.js +2 -0
  153. package/dist/migration/migrator.js.map +1 -0
  154. package/dist/migration/types.d.ts +52 -0
  155. package/dist/migration/types.d.ts.map +1 -0
  156. package/dist/migration/types.js +2 -0
  157. package/dist/migration/types.js.map +1 -0
  158. package/dist/smd/smd-manager.d.ts +28 -0
  159. package/dist/smd/smd-manager.d.ts.map +1 -0
  160. package/dist/smd/smd-manager.js +2 -0
  161. package/dist/smd/smd-manager.js.map +1 -0
  162. package/dist/smd/smd.d.ts +40 -0
  163. package/dist/smd/smd.d.ts.map +1 -0
  164. package/dist/smd/smd.js +2 -0
  165. package/dist/smd/smd.js.map +1 -0
  166. package/dist/syncer/index.d.ts +2 -0
  167. package/dist/syncer/index.d.ts.map +1 -0
  168. package/dist/syncer/index.js +2 -0
  169. package/dist/syncer/index.js.map +1 -0
  170. package/dist/syncer/syncer.d.ts +127 -0
  171. package/dist/syncer/syncer.d.ts.map +1 -0
  172. package/dist/syncer/syncer.js +2 -0
  173. package/dist/syncer/syncer.js.map +1 -0
  174. package/dist/templates/base-template.d.ts +13 -0
  175. package/dist/templates/base-template.d.ts.map +1 -0
  176. package/dist/templates/base-template.js +2 -0
  177. package/dist/templates/base-template.js.map +1 -0
  178. package/dist/templates/entity.template.d.ts +17 -0
  179. package/dist/templates/entity.template.d.ts.map +1 -0
  180. package/dist/templates/entity.template.js +2 -0
  181. package/dist/templates/entity.template.js.map +1 -0
  182. package/dist/templates/generated.template.d.ts +27 -0
  183. package/dist/templates/generated.template.d.ts.map +1 -0
  184. package/dist/templates/generated.template.js +2 -0
  185. package/dist/templates/generated.template.js.map +1 -0
  186. package/dist/templates/generated_http.template.d.ts +24 -0
  187. package/dist/templates/generated_http.template.d.ts.map +1 -0
  188. package/dist/templates/generated_http.template.js +2 -0
  189. package/dist/templates/generated_http.template.js.map +1 -0
  190. package/dist/templates/generated_sso.template.d.ts +20 -0
  191. package/dist/templates/generated_sso.template.d.ts.map +1 -0
  192. package/dist/templates/generated_sso.template.js +2 -0
  193. package/dist/templates/generated_sso.template.js.map +1 -0
  194. package/dist/templates/index.d.ts +2 -0
  195. package/dist/templates/index.d.ts.map +1 -0
  196. package/dist/templates/index.js +2 -0
  197. package/dist/templates/index.js.map +1 -0
  198. package/dist/templates/init_types.template.d.ts +17 -0
  199. package/dist/templates/init_types.template.d.ts.map +1 -0
  200. package/dist/templates/init_types.template.js +2 -0
  201. package/dist/templates/init_types.template.js.map +1 -0
  202. package/dist/templates/model.template.d.ts +17 -0
  203. package/dist/templates/model.template.d.ts.map +1 -0
  204. package/dist/templates/model.template.js +2 -0
  205. package/dist/templates/model.template.js.map +1 -0
  206. package/dist/templates/model_test.template.d.ts +17 -0
  207. package/dist/templates/model_test.template.d.ts.map +1 -0
  208. package/dist/templates/model_test.template.js +2 -0
  209. package/dist/templates/model_test.template.js.map +1 -0
  210. package/dist/templates/service.template.d.ts +29 -0
  211. package/dist/templates/service.template.d.ts.map +1 -0
  212. package/dist/templates/service.template.js +2 -0
  213. package/dist/templates/service.template.js.map +1 -0
  214. package/dist/templates/view_enums_buttonset.template.d.ts +17 -0
  215. package/dist/templates/view_enums_buttonset.template.d.ts.map +1 -0
  216. package/dist/templates/view_enums_buttonset.template.js +2 -0
  217. package/dist/templates/view_enums_buttonset.template.js.map +1 -0
  218. package/dist/templates/view_enums_dropdown.template.d.ts +18 -0
  219. package/dist/templates/view_enums_dropdown.template.d.ts.map +1 -0
  220. package/dist/templates/view_enums_dropdown.template.js +2 -0
  221. package/dist/templates/view_enums_dropdown.template.js.map +1 -0
  222. package/dist/templates/view_enums_select.template.d.ts +17 -0
  223. package/dist/templates/view_enums_select.template.d.ts.map +1 -0
  224. package/dist/templates/view_enums_select.template.js +2 -0
  225. package/dist/templates/view_enums_select.template.js.map +1 -0
  226. package/dist/templates/view_form.template.d.ts +26 -0
  227. package/dist/templates/view_form.template.d.ts.map +1 -0
  228. package/dist/templates/view_form.template.js +2 -0
  229. package/dist/templates/view_form.template.js.map +1 -0
  230. package/dist/templates/view_id_all_select.template.d.ts +17 -0
  231. package/dist/templates/view_id_all_select.template.d.ts.map +1 -0
  232. package/dist/templates/view_id_all_select.template.js +2 -0
  233. package/dist/templates/view_id_all_select.template.js.map +1 -0
  234. package/dist/templates/view_id_async_select.template.d.ts +17 -0
  235. package/dist/templates/view_id_async_select.template.d.ts.map +1 -0
  236. package/dist/templates/view_id_async_select.template.js +2 -0
  237. package/dist/templates/view_id_async_select.template.js.map +1 -0
  238. package/dist/templates/view_list.template.d.ts +38 -0
  239. package/dist/templates/view_list.template.d.ts.map +1 -0
  240. package/dist/templates/view_list.template.js +2 -0
  241. package/dist/templates/view_list.template.js.map +1 -0
  242. package/dist/templates/view_list_columns.template.d.ts +17 -0
  243. package/dist/templates/view_list_columns.template.d.ts.map +1 -0
  244. package/dist/templates/view_list_columns.template.js +2 -0
  245. package/dist/templates/view_list_columns.template.js.map +1 -0
  246. package/dist/templates/view_search_input.template.d.ts +17 -0
  247. package/dist/templates/view_search_input.template.d.ts.map +1 -0
  248. package/dist/templates/view_search_input.template.js +2 -0
  249. package/dist/templates/view_search_input.template.js.map +1 -0
  250. package/dist/testing/_relation-graph.d.ts +7 -0
  251. package/dist/testing/_relation-graph.d.ts.map +1 -0
  252. package/dist/testing/_relation-graph.js +2 -0
  253. package/dist/testing/_relation-graph.js.map +1 -0
  254. package/dist/testing/fixture-manager.d.ts +35 -0
  255. package/dist/testing/fixture-manager.d.ts.map +1 -0
  256. package/dist/testing/fixture-manager.js +2 -0
  257. package/dist/testing/fixture-manager.js.map +1 -0
  258. package/dist/types/types.d.ts +609 -0
  259. package/dist/types/types.d.ts.map +1 -0
  260. package/dist/types/types.js +2 -0
  261. package/dist/types/types.js.map +1 -0
  262. package/dist/typings/knex.d.js +2 -0
  263. package/dist/typings/knex.d.js.map +1 -0
  264. package/dist/utils/async-utils.d.ts +25 -0
  265. package/dist/utils/async-utils.d.ts.map +1 -0
  266. package/dist/utils/async-utils.js +2 -0
  267. package/dist/utils/async-utils.js.map +1 -0
  268. package/dist/utils/controller.d.ts +9 -0
  269. package/dist/utils/controller.d.ts.map +1 -0
  270. package/dist/utils/controller.js +2 -0
  271. package/dist/utils/controller.js.map +1 -0
  272. package/dist/utils/fs-utils.d.ts +9 -0
  273. package/dist/utils/fs-utils.d.ts.map +1 -0
  274. package/dist/utils/fs-utils.js +2 -0
  275. package/dist/utils/fs-utils.js.map +1 -0
  276. package/dist/utils/lodash-able.d.ts +2 -0
  277. package/dist/utils/lodash-able.d.ts.map +1 -0
  278. package/dist/utils/lodash-able.js +2 -0
  279. package/dist/utils/lodash-able.js.map +1 -0
  280. package/dist/utils/model.d.ts +17 -0
  281. package/dist/utils/model.d.ts.map +1 -0
  282. package/dist/utils/model.js +2 -0
  283. package/dist/utils/model.js.map +1 -0
  284. package/dist/utils/sql-parser.d.ts +4 -0
  285. package/dist/utils/sql-parser.d.ts.map +1 -0
  286. package/dist/utils/sql-parser.js +2 -0
  287. package/dist/utils/sql-parser.js.map +1 -0
  288. package/dist/utils/utils.d.ts +9 -0
  289. package/dist/utils/utils.d.ts.map +1 -0
  290. package/dist/utils/utils.js +2 -0
  291. package/dist/utils/utils.js.map +1 -0
  292. package/dist/utils/zod-error.d.ts +8 -0
  293. package/dist/utils/zod-error.d.ts.map +1 -0
  294. package/dist/utils/zod-error.js +2 -0
  295. package/dist/utils/zod-error.js.map +1 -0
  296. package/nodemon.json +6 -0
  297. package/package.json +29 -44
  298. package/src/api/base-frame.ts +3 -4
  299. package/src/api/caster.ts +22 -23
  300. package/src/api/code-converters.ts +170 -134
  301. package/src/api/context.ts +13 -6
  302. package/src/api/decorators.ts +146 -20
  303. package/src/api/index.ts +2 -0
  304. package/src/api/sonamu.ts +374 -165
  305. package/src/bin/build-config.ts +5 -0
  306. package/src/bin/cli-wrapper.ts +29 -40
  307. package/src/bin/cli.ts +132 -190
  308. package/src/database/_batch_update.ts +10 -15
  309. package/src/database/base-model.ts +300 -216
  310. package/src/database/db.ts +191 -21
  311. package/src/database/{drivers/knex/plugins → knex-plugins}/knex-on-duplicate-update.ts +1 -1
  312. package/src/database/puri-wrapper.ts +129 -0
  313. package/src/database/puri.ts +808 -0
  314. package/src/database/puri.types.ts +222 -0
  315. package/src/database/transaction-context.ts +18 -0
  316. package/src/database/upsert-builder.ts +32 -35
  317. package/src/entity/entity-manager.ts +7 -15
  318. package/src/entity/entity.ts +9 -31
  319. package/src/entity/migrator-/354/235/264/354/202/254/352/260/224/354/226/264/354/232/224.md +1 -0
  320. package/src/file-storage/driver.ts +121 -0
  321. package/src/file-storage/file-storage.ts +100 -0
  322. package/src/index.ts +14 -11
  323. package/src/migration/code-generation.ts +777 -0
  324. package/src/migration/migration-set.ts +453 -0
  325. package/src/migration/migrator.ts +823 -0
  326. package/src/migration/types.ts +53 -0
  327. package/src/shared/web.shared.ts.txt +33 -2
  328. package/src/syncer/syncer.ts +294 -127
  329. package/src/templates/generated.template.ts +13 -1
  330. package/src/templates/generated_http.template.ts +15 -12
  331. package/src/templates/generated_sso.template.ts +50 -2
  332. package/src/templates/model.template.ts +138 -2
  333. package/src/templates/service.template.ts +0 -1
  334. package/src/templates/view_form.template.ts +11 -7
  335. package/src/templates/view_list.template.ts +12 -4
  336. package/src/testing/fixture-manager.ts +229 -174
  337. package/src/types/types.ts +102 -14
  338. package/src/utils/async-utils.ts +64 -0
  339. package/src/utils/fs-utils.ts +17 -0
  340. package/src/utils/model.ts +0 -2
  341. package/src/utils/utils.ts +14 -58
  342. package/src/utils/zod-error.ts +12 -176
  343. package/tsconfig.json +2 -0
  344. package/tsup.config.js +4 -2
  345. package/.pnp.cjs +0 -14363
  346. package/.pnp.loader.mjs +0 -2047
  347. package/.vscode/extensions.json +0 -6
  348. package/.vscode/settings.json +0 -9
  349. package/.yarnrc.yml +0 -5
  350. package/dist/chunk-QJFHDCBN.mjs.map +0 -1
  351. package/src/database/base-model.abstract.ts +0 -97
  352. package/src/database/db.abstract.ts +0 -75
  353. package/src/database/drivers/knex/base-model.ts +0 -55
  354. package/src/database/drivers/knex/client.ts +0 -209
  355. package/src/database/drivers/knex/db.ts +0 -232
  356. package/src/database/drivers/knex/generator.ts +0 -659
  357. package/src/database/drivers/kysely/base-model.ts +0 -89
  358. package/src/database/drivers/kysely/client.ts +0 -309
  359. package/src/database/drivers/kysely/db.ts +0 -238
  360. package/src/database/drivers/kysely/generator.ts +0 -714
  361. package/src/database/types.ts +0 -118
  362. package/src/entity/migrator.ts +0 -1400
  363. package/src/smd/smd-manager.ts +0 -139
  364. package/src/smd/smd.ts +0 -571
  365. package/src/templates/kysely_types.template.ts +0 -205
  366. /package/dist/{chunk-NI37CY4T.mjs.map → chunk-C3IPIF6O.mjs.map} +0 -0
  367. /package/dist/{chunk-DYFCACHD.js.map → chunk-EXHKSVTE.js.map} +0 -0
  368. /package/dist/{chunk-DDJ7T4MA.mjs.map → chunk-HGIBJYOU.mjs.map} +0 -0
  369. /package/dist/{chunk-NIFOTHBW.mjs.map → chunk-JKSOJRQA.mjs.map} +0 -0
  370. /package/dist/{chunk-CXAVBVKC.js.map → chunk-OTKKFP3Y.js.map} +0 -0
  371. /package/dist/{chunk-J6S43O7G.js.map → chunk-UZ2IY5VE.js.map} +0 -0
@@ -0,0 +1,453 @@
1
+ import { Knex } from "knex";
2
+ import { DBColumn, DBForeign, DBIndex } from "./types";
3
+ import _ from "lodash";
4
+ import inflection from "inflection";
5
+ import { Entity } from "../entity/entity";
6
+ import { EntityManager } from "../entity/entity-manager";
7
+ import {
8
+ isKnexError,
9
+ MigrationSet,
10
+ RelationOn,
11
+ isBelongsToOneRelationProp,
12
+ isDecimalProp,
13
+ isEnumProp,
14
+ isFloatProp,
15
+ isHasManyRelationProp,
16
+ isIntegerProp,
17
+ isManyToManyRelationProp,
18
+ isOneToOneRelationProp,
19
+ isRelationProp,
20
+ isStringProp,
21
+ isTextProp,
22
+ isVirtualProp,
23
+ KnexColumnType,
24
+ MigrationColumn,
25
+ MigrationForeign,
26
+ MigrationIndex,
27
+ MigrationJoinTable,
28
+ MigrationSetAndJoinTable,
29
+ } from "../types/types";
30
+
31
+ /**
32
+ * DB에서 테이블 정보를 읽어서 MigrationSet을 만들어옵니다.
33
+ * @param compareDB Knex 인스턴스
34
+ * @param table 테이블 이름
35
+ * @returns MigrationSet 객체
36
+ */
37
+ export async function getMigrationSetFromDB(
38
+ compareDB: Knex,
39
+ table: string
40
+ ): Promise<MigrationSet | null> {
41
+ let dbColumns: DBColumn[], dbIndexes: DBIndex[], dbForeigns: DBForeign[];
42
+ try {
43
+ [dbColumns, dbIndexes, dbForeigns] = await readTable(compareDB, table);
44
+ } catch (e: unknown) {
45
+ if (isKnexError(e) && e.code === "ER_NO_SUCH_TABLE") {
46
+ return null;
47
+ }
48
+ console.error(e);
49
+ return null;
50
+ }
51
+
52
+ const columns: MigrationColumn[] = dbColumns.map((dbColumn) => {
53
+ const dbColType = resolveDBColType(dbColumn.Type, dbColumn.Field);
54
+ return {
55
+ name: dbColumn.Field,
56
+ nullable: dbColumn.Null !== "NO",
57
+ ...dbColType,
58
+ ...(() => {
59
+ if (dbColumn.Default !== null) {
60
+ return {
61
+ defaultTo: dbColumn.Default,
62
+ };
63
+ }
64
+ return {};
65
+ })(),
66
+ };
67
+ });
68
+
69
+ const dbIndexesGroup = _.groupBy(
70
+ dbIndexes.filter(
71
+ (dbIndex) =>
72
+ dbIndex.Key_name !== "PRIMARY" &&
73
+ !dbForeigns.find((dbForeign) => dbForeign.keyName === dbIndex.Key_name)
74
+ ),
75
+ (dbIndex) => dbIndex.Key_name
76
+ );
77
+
78
+ const parseIndexType = (index: DBIndex) => {
79
+ if (index.Index_type === "FULLTEXT") {
80
+ return "fulltext";
81
+ }
82
+ return index.Non_unique === 1 ? "index" : "unique";
83
+ };
84
+
85
+ // indexes 처리
86
+ const indexes: MigrationIndex[] = Object.keys(dbIndexesGroup).map(
87
+ (keyName) => {
88
+ const currentIndexes = dbIndexesGroup[keyName];
89
+ return {
90
+ type: parseIndexType(currentIndexes[0]),
91
+ columns: currentIndexes.map((currentIndex) => currentIndex.Column_name),
92
+ };
93
+ }
94
+ );
95
+ // console.log(table);
96
+ // console.table(dbIndexes);
97
+ // console.table(dbForeigns);
98
+
99
+ // foreigns 처리
100
+ const foreigns: MigrationForeign[] = dbForeigns.map((dbForeign) => {
101
+ return {
102
+ columns: [dbForeign.from],
103
+ to: `${dbForeign.referencesTable}.${dbForeign.referencesField}`,
104
+ onUpdate: dbForeign.onUpdate as RelationOn,
105
+ onDelete: dbForeign.onDelete as RelationOn,
106
+ };
107
+ });
108
+
109
+ return {
110
+ table,
111
+ columns,
112
+ indexes,
113
+ foreigns,
114
+ };
115
+ }
116
+
117
+ /*
118
+ * 기존 테이블 읽어서 cols, indexes 반환
119
+ */
120
+ async function readTable(
121
+ compareDB: Knex,
122
+ tableName: string
123
+ ): Promise<[DBColumn[], DBIndex[], DBForeign[]]> {
124
+ // 테이블 정보
125
+ try {
126
+ const [_cols] = (await compareDB.raw(`SHOW FIELDS FROM ${tableName}`)) as [
127
+ DBColumn[],
128
+ ];
129
+ const cols = _cols.map((col) => ({
130
+ ...col,
131
+ // Default 값은 숫자나 MySQL Expression이 아닌 경우 ""로 감싸줌
132
+ ...(col.Default !== null && {
133
+ Default:
134
+ col.Default.replace(/[0-9]+/g, "").length > 0 &&
135
+ col.Extra !== "DEFAULT_GENERATED"
136
+ ? `"${col.Default}"`
137
+ : col.Default,
138
+ }),
139
+ }));
140
+
141
+ const [indexes] = await compareDB.raw(`SHOW INDEX FROM ${tableName}`);
142
+ const [[row]] = await compareDB.raw(`SHOW CREATE TABLE ${tableName}`);
143
+ const ddl = row["Create Table"];
144
+ const matched = ddl.match(/CONSTRAINT .+/g);
145
+ const foreignKeys = (matched ?? []).map((line: string) => {
146
+ // 해당 라인을 정규식으로 파싱
147
+ const matched = line.match(
148
+ /CONSTRAINT `(.+)` FOREIGN KEY \(`(.+)`\) REFERENCES `(.+)` \(`(.+)`\)( ON [A-Z ]+)*/
149
+ );
150
+ if (!matched) {
151
+ throw new Error(`인식할 수 없는 FOREIGN KEY CONSTRAINT ${line}`);
152
+ }
153
+ const [, keyName, from, referencesTable, referencesField, onClause] =
154
+ matched;
155
+ // console.debug({ tableName, line, onClause });
156
+
157
+ const [onUpdateFull, _onUpdate] =
158
+ (onClause ?? "").match(/ON UPDATE ([A-Z ]+)$/) ?? [];
159
+ const onUpdate = _onUpdate ?? "NO ACTION";
160
+
161
+ const onDelete =
162
+ (onClause ?? "")
163
+ .replace(onUpdateFull ?? "", "")
164
+ .match(/ON DELETE ([A-Z ]+)/)?.[1]
165
+ ?.trim() ?? "NO ACTION";
166
+
167
+ return {
168
+ keyName,
169
+ from,
170
+ referencesTable,
171
+ referencesField,
172
+ onDelete,
173
+ onUpdate,
174
+ };
175
+ });
176
+ return [cols, indexes, foreignKeys];
177
+ } catch (e) {
178
+ throw e;
179
+ }
180
+ }
181
+
182
+ function resolveDBColType(
183
+ colType: string,
184
+ colField: string
185
+ ): Pick<
186
+ MigrationColumn,
187
+ "type" | "unsigned" | "length" | "precision" | "scale"
188
+ > {
189
+ let [rawType, unsigned] = colType.split(" ");
190
+ const matched = rawType.match(/\(([0-9]+)\)/);
191
+ let length;
192
+ if (matched !== null && matched[1]) {
193
+ rawType = rawType.replace(/\(([0-9]+)\)/, "");
194
+ length = parseInt(matched[1]);
195
+ }
196
+
197
+ if (rawType === "char" && colField === "uuid") {
198
+ return {
199
+ type: "uuid",
200
+ };
201
+ }
202
+
203
+ switch (rawType) {
204
+ case "int":
205
+ return {
206
+ type: "integer",
207
+ unsigned: unsigned === "unsigned",
208
+ };
209
+ case "varchar":
210
+ // case "char":
211
+ return {
212
+ type: "string",
213
+ ...(length !== undefined && {
214
+ length,
215
+ }),
216
+ };
217
+ case "text":
218
+ case "mediumtext":
219
+ case "longtext":
220
+ case "timestamp":
221
+ case "json":
222
+ case "date":
223
+ case "time":
224
+ return {
225
+ type: rawType,
226
+ };
227
+ case "datetime":
228
+ return {
229
+ type: "datetime",
230
+ };
231
+ case "tinyint":
232
+ return {
233
+ type: "boolean",
234
+ };
235
+ default:
236
+ // decimal 처리
237
+ if (rawType.startsWith("decimal")) {
238
+ const [, precision, scale] =
239
+ rawType.match(/decimal\(([0-9]+),([0-9]+)\)/) ?? [];
240
+ return {
241
+ type: "decimal",
242
+ precision: parseInt(precision),
243
+ scale: parseInt(scale),
244
+ ...(unsigned === "unsigned" && {
245
+ unsigned: true,
246
+ }),
247
+ };
248
+ } else if (rawType.startsWith("float")) {
249
+ const [, precision, scale] =
250
+ rawType.match(/float\(([0-9]+),([0-9]+)\)/) ?? [];
251
+ return {
252
+ type: "float",
253
+ precision: parseInt(precision),
254
+ scale: parseInt(scale),
255
+ ...(unsigned === "unsigned" && {
256
+ unsigned: true,
257
+ }),
258
+ };
259
+ }
260
+ throw new Error(`resolve 불가능한 DB컬럼 타입 ${colType} ${rawType}`);
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Entity를 읽어서 MigrationSetAndJoinTable을 만들어옵니다.
266
+ * @param entity Entity 객체
267
+ * @returns MigrationSetAndJoinTable 객체
268
+ */
269
+ export function getMigrationSetFromEntity(
270
+ entity: Entity
271
+ ): MigrationSetAndJoinTable {
272
+ const migrationSet: MigrationSetAndJoinTable = entity.props.reduce(
273
+ (r, prop) => {
274
+ // virtual 필드 제외
275
+ if (isVirtualProp(prop)) {
276
+ return r;
277
+ }
278
+ // HasMany 케이스는 아무 처리도 하지 않음
279
+ if (isHasManyRelationProp(prop)) {
280
+ return r;
281
+ }
282
+
283
+ // 일반 컬럼
284
+ if (!isRelationProp(prop)) {
285
+ // type resolve
286
+ let type: KnexColumnType;
287
+ if (isTextProp(prop)) {
288
+ type = prop.textType;
289
+ } else if (isEnumProp(prop)) {
290
+ type = "string";
291
+ } else {
292
+ type = prop.type as KnexColumnType;
293
+ }
294
+
295
+ const column = {
296
+ name: prop.name,
297
+ type,
298
+ ...(isIntegerProp(prop) && { unsigned: prop.unsigned === true }),
299
+ ...((isStringProp(prop) || isEnumProp(prop)) && {
300
+ length: prop.length,
301
+ }),
302
+ nullable: prop.nullable === true,
303
+ ...(() => {
304
+ if (prop.dbDefault !== undefined) {
305
+ return {
306
+ defaultTo: prop.dbDefault,
307
+ };
308
+ }
309
+ return {};
310
+ })(),
311
+ // FIXME: float(N, M) deprecated
312
+ // Decimal, Float 타입의 경우 precision, scale 추가
313
+ ...((isDecimalProp(prop) || isFloatProp(prop)) && {
314
+ precision: prop.precision ?? 8,
315
+ scale: prop.scale ?? 2,
316
+ }),
317
+ };
318
+
319
+ r.columns.push(column);
320
+ }
321
+
322
+ if (isManyToManyRelationProp(prop)) {
323
+ // ManyToMany 케이스
324
+ const relMd = EntityManager.get(prop.with);
325
+ const table1 = entity.table;
326
+ const table2 = relMd.table;
327
+ const join = {
328
+ from: `${entity.table}.id`,
329
+ through: {
330
+ from: `${prop.joinTable}.${inflection.singularize(table1)}_id`,
331
+ to: `${prop.joinTable}.${inflection.singularize(table2)}_id`,
332
+ onUpdate: prop.onUpdate,
333
+ onDelete: prop.onDelete,
334
+ },
335
+ to: `${relMd.table}.id`,
336
+ };
337
+ const through = join.through;
338
+ const fields = [through.from, through.to];
339
+ r.joinTables.push({
340
+ table: through.from.split(".")[0],
341
+ indexes: [
342
+ {
343
+ type: "unique",
344
+ columns: ["uuid"],
345
+ },
346
+ // 조인 테이블에 걸린 인덱스 찾아와서 연결
347
+ ...entity.indexes
348
+ .filter((index) =>
349
+ index.columns.find((col) => col.includes(prop.joinTable + "."))
350
+ )
351
+ .map((index) => ({
352
+ ...index,
353
+ columns: index.columns.map((col) =>
354
+ col.replace(prop.joinTable + ".", "")
355
+ ),
356
+ })),
357
+ ],
358
+ columns: [
359
+ {
360
+ name: "id",
361
+ type: "integer",
362
+ nullable: false,
363
+ unsigned: true,
364
+ },
365
+ ...fields.map((field) => {
366
+ return {
367
+ name: field.split(".")[1],
368
+ type: "integer",
369
+ nullable: false,
370
+ unsigned: true,
371
+ } as MigrationColumn;
372
+ }),
373
+ {
374
+ name: "uuid",
375
+ nullable: true,
376
+ type: "uuid",
377
+ },
378
+ ],
379
+ foreigns: fields.map((field) => {
380
+ // 현재 필드가 어떤 테이블에 속하는지 판단
381
+ const col = field.split(".")[1];
382
+ const to = (() => {
383
+ if (
384
+ inflection.singularize(join.to.split(".")[0]) + "_id" ===
385
+ col
386
+ ) {
387
+ return join.to;
388
+ } else {
389
+ return join.from;
390
+ }
391
+ })();
392
+ return {
393
+ columns: [col],
394
+ to,
395
+ onUpdate: through.onUpdate,
396
+ onDelete: through.onDelete,
397
+ };
398
+ }),
399
+ });
400
+ return r;
401
+ } else if (
402
+ isBelongsToOneRelationProp(prop) ||
403
+ (isOneToOneRelationProp(prop) && prop.hasJoinColumn)
404
+ ) {
405
+ // -OneRelation 케이스
406
+ const idColumnName = prop.name + "_id";
407
+ r.columns.push({
408
+ name: idColumnName,
409
+ type: "integer",
410
+ unsigned: true,
411
+ nullable: prop.nullable ?? false,
412
+ });
413
+ if ((prop.useConstraint ?? true) === true) {
414
+ r.foreigns.push({
415
+ columns: [idColumnName],
416
+ to: `${inflection
417
+ .underscore(inflection.pluralize(prop.with))
418
+ .toLowerCase()}.id`,
419
+ onUpdate: prop.onUpdate ?? "RESTRICT",
420
+ onDelete: prop.onDelete ?? "RESTRICT",
421
+ });
422
+ }
423
+ }
424
+
425
+ return r;
426
+ },
427
+ {
428
+ table: entity.table,
429
+ columns: [] as MigrationColumn[],
430
+ indexes: [] as MigrationIndex[],
431
+ foreigns: [] as MigrationForeign[],
432
+ joinTables: [] as MigrationJoinTable[],
433
+ }
434
+ );
435
+
436
+ // indexes
437
+ migrationSet.indexes = entity.indexes.filter((index) =>
438
+ index.columns.find((col) => col.includes(".") === false)
439
+ );
440
+
441
+ // uuid
442
+ migrationSet.columns = migrationSet.columns.concat({
443
+ name: "uuid",
444
+ nullable: true,
445
+ type: "uuid",
446
+ } as MigrationColumn);
447
+ migrationSet.indexes = migrationSet.indexes.concat({
448
+ type: "unique",
449
+ columns: ["uuid"],
450
+ } as MigrationIndex);
451
+
452
+ return migrationSet;
453
+ }