sonamu 0.6.0 → 0.7.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 (406) hide show
  1. package/.swcrc.project-default +18 -0
  2. package/bin/cli.js +24 -0
  3. package/dist/ai/agents/agent.d.ts +11 -0
  4. package/dist/ai/agents/agent.d.ts.map +1 -0
  5. package/dist/ai/agents/agent.js +65 -0
  6. package/dist/ai/agents/index.d.ts +3 -0
  7. package/dist/ai/agents/index.d.ts.map +1 -0
  8. package/dist/ai/agents/index.js +4 -0
  9. package/dist/ai/agents/types.d.ts +43 -0
  10. package/dist/ai/agents/types.d.ts.map +1 -0
  11. package/dist/ai/agents/types.js +3 -0
  12. package/dist/ai/index.d.ts +2 -0
  13. package/dist/ai/index.d.ts.map +1 -0
  14. package/dist/ai/index.js +3 -0
  15. package/dist/ai/providers/rtzr/api.d.ts +22 -0
  16. package/dist/ai/providers/rtzr/api.d.ts.map +1 -0
  17. package/dist/ai/providers/rtzr/api.js +28 -0
  18. package/dist/ai/providers/rtzr/error.d.ts +18 -0
  19. package/dist/ai/providers/rtzr/error.d.ts.map +1 -0
  20. package/dist/ai/providers/rtzr/error.js +29 -0
  21. package/dist/ai/providers/rtzr/index.d.ts +5 -0
  22. package/dist/ai/providers/rtzr/index.d.ts.map +1 -0
  23. package/dist/ai/providers/rtzr/index.js +6 -0
  24. package/dist/ai/providers/rtzr/model.d.ts +52 -0
  25. package/dist/ai/providers/rtzr/model.d.ts.map +1 -0
  26. package/dist/ai/providers/rtzr/model.js +137 -0
  27. package/dist/ai/providers/rtzr/options.d.ts +7 -0
  28. package/dist/ai/providers/rtzr/options.d.ts.map +1 -0
  29. package/dist/ai/providers/rtzr/options.js +47 -0
  30. package/dist/ai/providers/rtzr/provider.d.ts +18 -0
  31. package/dist/ai/providers/rtzr/provider.d.ts.map +1 -0
  32. package/dist/ai/providers/rtzr/provider.js +54 -0
  33. package/dist/ai/providers/rtzr/utils.d.ts +19 -0
  34. package/dist/ai/providers/rtzr/utils.d.ts.map +1 -0
  35. package/dist/ai/providers/rtzr/utils.js +88 -0
  36. package/dist/api/base-frame.d.ts +2 -2
  37. package/dist/api/base-frame.d.ts.map +1 -1
  38. package/dist/api/base-frame.js +2 -1
  39. package/dist/api/caster.d.ts.map +1 -1
  40. package/dist/api/caster.js +6 -1
  41. package/dist/api/code-converters.d.ts +58 -14
  42. package/dist/api/code-converters.d.ts.map +1 -1
  43. package/dist/api/code-converters.js +178 -409
  44. package/dist/api/config.d.ts +27 -13
  45. package/dist/api/config.d.ts.map +1 -1
  46. package/dist/api/config.js +19 -26
  47. package/dist/api/context.d.ts +4 -3
  48. package/dist/api/context.d.ts.map +1 -1
  49. package/dist/api/context.js +1 -1
  50. package/dist/api/decorators.d.ts +20 -6
  51. package/dist/api/decorators.d.ts.map +1 -1
  52. package/dist/api/decorators.js +111 -18
  53. package/dist/api/index.d.ts +2 -2
  54. package/dist/api/index.d.ts.map +1 -1
  55. package/dist/api/index.js +3 -3
  56. package/dist/api/sonamu.d.ts +7 -7
  57. package/dist/api/sonamu.d.ts.map +1 -1
  58. package/dist/api/sonamu.js +83 -51
  59. package/dist/api/validator.d.ts +6 -0
  60. package/dist/api/validator.d.ts.map +1 -0
  61. package/dist/api/validator.js +81 -0
  62. package/dist/bin/build-config.d.ts +5 -1
  63. package/dist/bin/build-config.d.ts.map +1 -1
  64. package/dist/bin/build-config.js +5 -2
  65. package/dist/bin/cli.js +165 -64
  66. package/dist/bin/loader-register.d.ts +2 -0
  67. package/dist/bin/loader-register.d.ts.map +1 -0
  68. package/dist/bin/loader-register.js +34 -0
  69. package/dist/database/_batch_update.d.ts +5 -3
  70. package/dist/database/_batch_update.d.ts.map +1 -1
  71. package/dist/database/_batch_update.js +30 -13
  72. package/dist/database/base-model.d.ts +96 -10
  73. package/dist/database/base-model.d.ts.map +1 -1
  74. package/dist/database/base-model.js +232 -89
  75. package/dist/database/base-model.types.d.ts +93 -0
  76. package/dist/database/base-model.types.d.ts.map +1 -0
  77. package/dist/database/base-model.types.js +10 -0
  78. package/dist/database/code-generator.d.ts +1 -1
  79. package/dist/database/code-generator.d.ts.map +1 -1
  80. package/dist/database/code-generator.js +11 -10
  81. package/dist/database/db.d.ts +5 -6
  82. package/dist/database/db.d.ts.map +1 -1
  83. package/dist/database/db.js +22 -25
  84. package/dist/database/puri-subset.test-d.js +81 -0
  85. package/dist/database/puri-subset.types.d.ts +123 -0
  86. package/dist/database/puri-subset.types.d.ts.map +1 -0
  87. package/dist/database/puri-subset.types.js +16 -0
  88. package/dist/database/puri-wrapper.d.ts +13 -11
  89. package/dist/database/puri-wrapper.d.ts.map +1 -1
  90. package/dist/database/puri-wrapper.js +2 -2
  91. package/dist/database/puri.d.ts +25 -14
  92. package/dist/database/puri.d.ts.map +1 -1
  93. package/dist/database/puri.js +83 -21
  94. package/dist/database/puri.types.d.ts +21 -7
  95. package/dist/database/puri.types.d.ts.map +1 -1
  96. package/dist/database/puri.types.js +4 -1
  97. package/dist/database/transaction-context.d.ts +1 -1
  98. package/dist/database/transaction-context.d.ts.map +1 -1
  99. package/dist/database/transaction-context.js +1 -1
  100. package/dist/database/upsert-builder.d.ts +9 -3
  101. package/dist/database/upsert-builder.d.ts.map +1 -1
  102. package/dist/database/upsert-builder.js +228 -78
  103. package/dist/entity/entity-manager.d.ts +165 -2
  104. package/dist/entity/entity-manager.d.ts.map +1 -1
  105. package/dist/entity/entity-manager.js +26 -10
  106. package/dist/entity/entity.d.ts +5 -3
  107. package/dist/entity/entity.d.ts.map +1 -1
  108. package/dist/entity/entity.js +153 -54
  109. package/dist/exceptions/error-handler.d.ts +1 -1
  110. package/dist/exceptions/error-handler.d.ts.map +1 -1
  111. package/dist/exceptions/error-handler.js +1 -1
  112. package/dist/exceptions/so-exceptions.d.ts +1 -1
  113. package/dist/exceptions/so-exceptions.d.ts.map +1 -1
  114. package/dist/exceptions/so-exceptions.js +1 -1
  115. package/dist/file-storage/driver.d.ts +1 -1
  116. package/dist/file-storage/driver.d.ts.map +1 -1
  117. package/dist/file-storage/driver.js +1 -1
  118. package/dist/file-storage/file-storage.js +2 -2
  119. package/dist/index.d.ts +18 -11
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +19 -13
  122. package/dist/migration/code-generation.d.ts +1 -1
  123. package/dist/migration/code-generation.d.ts.map +1 -1
  124. package/dist/migration/code-generation.js +123 -67
  125. package/dist/migration/migration-set.d.ts +2 -10
  126. package/dist/migration/migration-set.d.ts.map +1 -1
  127. package/dist/migration/migration-set.js +67 -218
  128. package/dist/migration/migrator.d.ts +24 -73
  129. package/dist/migration/migrator.d.ts.map +1 -1
  130. package/dist/migration/migrator.js +121 -301
  131. package/dist/migration/postgresql-schema-reader.d.ts +51 -0
  132. package/dist/migration/postgresql-schema-reader.d.ts.map +1 -0
  133. package/dist/migration/postgresql-schema-reader.js +245 -0
  134. package/dist/migration/types.d.ts +6 -38
  135. package/dist/migration/types.d.ts.map +1 -1
  136. package/dist/migration/types.js +1 -1
  137. package/dist/naite/messaging-types.d.ts +43 -0
  138. package/dist/naite/messaging-types.d.ts.map +1 -0
  139. package/dist/naite/messaging-types.js +7 -0
  140. package/dist/naite/naite-reporter.d.ts +41 -0
  141. package/dist/naite/naite-reporter.d.ts.map +1 -0
  142. package/dist/naite/naite-reporter.js +102 -0
  143. package/dist/naite/naite.d.ts +91 -8
  144. package/dist/naite/naite.d.ts.map +1 -1
  145. package/dist/naite/naite.js +285 -41
  146. package/dist/stream/sse.d.ts +2 -2
  147. package/dist/stream/sse.d.ts.map +1 -1
  148. package/dist/stream/sse.js +1 -1
  149. package/dist/syncer/api-parser.d.ts +3 -13
  150. package/dist/syncer/api-parser.d.ts.map +1 -1
  151. package/dist/syncer/api-parser.js +67 -56
  152. package/dist/syncer/checksum.d.ts +2 -2
  153. package/dist/syncer/checksum.d.ts.map +1 -1
  154. package/dist/syncer/checksum.js +11 -11
  155. package/dist/syncer/code-generator.d.ts +3 -3
  156. package/dist/syncer/code-generator.d.ts.map +1 -1
  157. package/dist/syncer/code-generator.js +37 -17
  158. package/dist/syncer/entity-operations.d.ts +2 -2
  159. package/dist/syncer/entity-operations.d.ts.map +1 -1
  160. package/dist/syncer/entity-operations.js +9 -8
  161. package/dist/syncer/file-patterns.d.ts +1 -1
  162. package/dist/syncer/file-patterns.d.ts.map +1 -1
  163. package/dist/syncer/file-patterns.js +1 -1
  164. package/dist/syncer/index.d.ts +4 -4
  165. package/dist/syncer/index.d.ts.map +1 -1
  166. package/dist/syncer/index.js +5 -5
  167. package/dist/syncer/module-loader.d.ts +4 -4
  168. package/dist/syncer/module-loader.d.ts.map +1 -1
  169. package/dist/syncer/module-loader.js +17 -12
  170. package/dist/syncer/syncer.d.ts +31 -24
  171. package/dist/syncer/syncer.d.ts.map +1 -1
  172. package/dist/syncer/syncer.js +92 -45
  173. package/dist/template/entity-converter.d.ts +1 -1
  174. package/dist/template/entity-converter.d.ts.map +1 -1
  175. package/dist/template/entity-converter.js +15 -8
  176. package/dist/template/helpers.d.ts +2 -2
  177. package/dist/template/helpers.d.ts.map +1 -1
  178. package/dist/template/helpers.js +3 -3
  179. package/dist/template/implementations/entity.template.d.ts +2 -2
  180. package/dist/template/implementations/entity.template.d.ts.map +1 -1
  181. package/dist/template/implementations/entity.template.js +4 -5
  182. package/dist/template/implementations/generated.template.d.ts +2 -3
  183. package/dist/template/implementations/generated.template.d.ts.map +1 -1
  184. package/dist/template/implementations/generated.template.js +46 -29
  185. package/dist/template/implementations/generated_http.template.d.ts +2 -3
  186. package/dist/template/implementations/generated_http.template.d.ts.map +1 -1
  187. package/dist/template/implementations/generated_http.template.js +9 -9
  188. package/dist/template/implementations/generated_sso.template.d.ts +3 -4
  189. package/dist/template/implementations/generated_sso.template.d.ts.map +1 -1
  190. package/dist/template/implementations/generated_sso.template.js +54 -25
  191. package/dist/template/implementations/init_types.template.d.ts +2 -2
  192. package/dist/template/implementations/init_types.template.d.ts.map +1 -1
  193. package/dist/template/implementations/init_types.template.js +2 -2
  194. package/dist/template/implementations/model.template.d.ts +2 -2
  195. package/dist/template/implementations/model.template.d.ts.map +1 -1
  196. package/dist/template/implementations/model.template.js +47 -37
  197. package/dist/template/implementations/model_test.template.d.ts +2 -2
  198. package/dist/template/implementations/model_test.template.d.ts.map +1 -1
  199. package/dist/template/implementations/model_test.template.js +2 -2
  200. package/dist/template/implementations/service.template.d.ts +4 -4
  201. package/dist/template/implementations/service.template.d.ts.map +1 -1
  202. package/dist/template/implementations/service.template.js +24 -16
  203. package/dist/template/implementations/view_enums_buttonset.template.d.ts +2 -2
  204. package/dist/template/implementations/view_enums_buttonset.template.d.ts.map +1 -1
  205. package/dist/template/implementations/view_enums_buttonset.template.js +1 -1
  206. package/dist/template/implementations/view_enums_dropdown.template.d.ts +2 -2
  207. package/dist/template/implementations/view_enums_dropdown.template.d.ts.map +1 -1
  208. package/dist/template/implementations/view_enums_dropdown.template.js +2 -2
  209. package/dist/template/implementations/view_enums_select.template.d.ts +2 -2
  210. package/dist/template/implementations/view_enums_select.template.d.ts.map +1 -1
  211. package/dist/template/implementations/view_enums_select.template.js +2 -2
  212. package/dist/template/implementations/view_form.template.d.ts +2 -2
  213. package/dist/template/implementations/view_form.template.d.ts.map +1 -1
  214. package/dist/template/implementations/view_form.template.js +4 -4
  215. package/dist/template/implementations/view_id_all_select.template.d.ts +2 -2
  216. package/dist/template/implementations/view_id_all_select.template.d.ts.map +1 -1
  217. package/dist/template/implementations/view_id_all_select.template.js +1 -1
  218. package/dist/template/implementations/view_id_async_select.template.d.ts +2 -2
  219. package/dist/template/implementations/view_id_async_select.template.d.ts.map +1 -1
  220. package/dist/template/implementations/view_id_async_select.template.js +1 -1
  221. package/dist/template/implementations/view_list.template.d.ts +2 -2
  222. package/dist/template/implementations/view_list.template.d.ts.map +1 -1
  223. package/dist/template/implementations/view_list.template.js +29 -19
  224. package/dist/template/implementations/view_list_columns.template.d.ts +3 -3
  225. package/dist/template/implementations/view_list_columns.template.d.ts.map +1 -1
  226. package/dist/template/implementations/view_list_columns.template.js +1 -1
  227. package/dist/template/implementations/view_search_input.template.d.ts +2 -2
  228. package/dist/template/implementations/view_search_input.template.d.ts.map +1 -1
  229. package/dist/template/implementations/view_search_input.template.js +1 -1
  230. package/dist/template/index.d.ts +4 -2
  231. package/dist/template/index.d.ts.map +1 -1
  232. package/dist/template/index.js +5 -3
  233. package/dist/template/template-manager.d.ts +56 -0
  234. package/dist/template/template-manager.d.ts.map +1 -0
  235. package/dist/template/template-manager.js +125 -0
  236. package/dist/template/template-types.d.ts +16 -0
  237. package/dist/template/template-types.d.ts.map +1 -0
  238. package/dist/template/template-types.js +7 -0
  239. package/dist/template/template.d.ts +12 -2
  240. package/dist/template/template.d.ts.map +1 -1
  241. package/dist/template/template.js +19 -6
  242. package/dist/template/zod-converter.d.ts +40 -7
  243. package/dist/template/zod-converter.d.ts.map +1 -1
  244. package/dist/template/zod-converter.js +341 -58
  245. package/dist/testing/_relation-graph.d.ts +1 -1
  246. package/dist/testing/_relation-graph.d.ts.map +1 -1
  247. package/dist/testing/_relation-graph.js +12 -3
  248. package/dist/testing/fixture-manager.d.ts +42 -11
  249. package/dist/testing/fixture-manager.d.ts.map +1 -1
  250. package/dist/testing/fixture-manager.js +338 -236
  251. package/dist/types/types.d.ts +709 -104
  252. package/dist/types/types.d.ts.map +1 -1
  253. package/dist/types/types.js +309 -52
  254. package/dist/typings/knex.d.js +2 -2
  255. package/dist/utils/async-utils.d.ts.map +1 -1
  256. package/dist/utils/async-utils.js +3 -3
  257. package/dist/utils/console-util.js +1 -1
  258. package/dist/utils/controller.d.ts +1 -0
  259. package/dist/utils/controller.d.ts.map +1 -1
  260. package/dist/utils/controller.js +4 -1
  261. package/dist/utils/esm-utils.d.ts +0 -6
  262. package/dist/utils/esm-utils.d.ts.map +1 -1
  263. package/dist/utils/esm-utils.js +2 -9
  264. package/dist/utils/formatter.d.ts +3 -0
  265. package/dist/utils/formatter.d.ts.map +1 -0
  266. package/dist/utils/formatter.js +110 -0
  267. package/dist/utils/fs-utils.d.ts +1 -1
  268. package/dist/utils/fs-utils.d.ts.map +1 -1
  269. package/dist/utils/fs-utils.js +1 -1
  270. package/dist/utils/lodash-able.d.ts.map +1 -1
  271. package/dist/utils/lodash-able.js +1 -1
  272. package/dist/utils/object-utils.d.ts +44 -0
  273. package/dist/utils/object-utils.d.ts.map +1 -0
  274. package/dist/utils/object-utils.js +191 -0
  275. package/dist/utils/path-utils.d.ts +1 -1
  276. package/dist/utils/path-utils.d.ts.map +1 -1
  277. package/dist/utils/path-utils.js +3 -3
  278. package/dist/utils/process-utils.js +1 -1
  279. package/dist/utils/sql-parser.d.ts +5 -1
  280. package/dist/utils/sql-parser.d.ts.map +1 -1
  281. package/dist/utils/sql-parser.js +14 -3
  282. package/dist/utils/type-utils.d.ts +23 -0
  283. package/dist/utils/type-utils.d.ts.map +1 -0
  284. package/dist/utils/type-utils.js +45 -0
  285. package/dist/utils/utils.d.ts +7 -1
  286. package/dist/utils/utils.d.ts.map +1 -1
  287. package/dist/utils/utils.js +44 -5
  288. package/dist/utils/zod-error.d.ts +1 -1
  289. package/dist/utils/zod-error.d.ts.map +1 -1
  290. package/dist/utils/zod-error.js +1 -1
  291. package/package.json +54 -29
  292. package/src/ai/agents/agent.ts +87 -0
  293. package/src/ai/agents/index.ts +2 -0
  294. package/src/ai/agents/types.ts +47 -0
  295. package/src/ai/index.ts +1 -0
  296. package/src/ai/providers/rtzr/api.ts +37 -0
  297. package/src/ai/providers/rtzr/error.ts +34 -0
  298. package/src/ai/providers/rtzr/index.ts +4 -0
  299. package/src/ai/providers/rtzr/model.ts +201 -0
  300. package/src/ai/providers/rtzr/options.ts +49 -0
  301. package/src/ai/providers/rtzr/provider.ts +91 -0
  302. package/src/ai/providers/rtzr/utils.ts +127 -0
  303. package/src/api/base-frame.ts +4 -2
  304. package/src/api/caster.ts +17 -23
  305. package/src/api/code-converters.ts +176 -533
  306. package/src/api/config.ts +39 -56
  307. package/src/api/context.ts +7 -18
  308. package/src/api/decorators.ts +175 -46
  309. package/src/api/index.ts +2 -2
  310. package/src/api/sonamu.ts +133 -124
  311. package/src/api/validator.ts +83 -0
  312. package/src/bin/build-config.ts +7 -1
  313. package/src/bin/cli.ts +192 -110
  314. package/src/bin/loader-register.ts +38 -0
  315. package/src/database/_batch_update.ts +46 -31
  316. package/src/database/base-model.ts +390 -182
  317. package/src/database/base-model.types.ts +155 -0
  318. package/src/database/code-generator.ts +13 -32
  319. package/src/database/db.ts +36 -50
  320. package/src/database/puri-subset.test-d.ts +471 -0
  321. package/src/database/puri-subset.types.ts +195 -0
  322. package/src/database/puri-wrapper.ts +58 -67
  323. package/src/database/puri.ts +182 -126
  324. package/src/database/puri.types.ts +64 -31
  325. package/src/database/transaction-context.ts +1 -1
  326. package/src/database/upsert-builder.ts +262 -132
  327. package/src/entity/entity-manager.ts +36 -28
  328. package/src/entity/entity.ts +330 -249
  329. package/src/exceptions/error-handler.ts +3 -3
  330. package/src/exceptions/so-exceptions.ts +11 -11
  331. package/src/file-storage/driver.ts +5 -5
  332. package/src/file-storage/file-storage.ts +2 -2
  333. package/src/index.ts +18 -12
  334. package/src/migration/code-generation.ts +185 -172
  335. package/src/migration/migration-set.ts +80 -293
  336. package/src/migration/migrator.ts +182 -425
  337. package/src/migration/mysql-schema-reader.ts.txt +272 -0
  338. package/src/migration/postgresql-schema-reader.ts +310 -0
  339. package/src/migration/types.ts +6 -39
  340. package/src/naite/messaging-types.ts +51 -0
  341. package/src/naite/naite-reporter.ts +128 -0
  342. package/src/naite/naite.ts +378 -33
  343. package/src/shared/web.shared.ts.txt +20 -24
  344. package/src/stream/sse.ts +5 -5
  345. package/src/syncer/api-parser.ts +52 -69
  346. package/src/syncer/checksum.ts +25 -37
  347. package/src/syncer/code-generator.ts +58 -62
  348. package/src/syncer/entity-operations.ts +12 -15
  349. package/src/syncer/file-patterns.ts +2 -2
  350. package/src/syncer/index.ts +4 -4
  351. package/src/syncer/module-loader.ts +28 -25
  352. package/src/syncer/syncer.ts +155 -162
  353. package/src/template/entity-converter.ts +18 -27
  354. package/src/template/helpers.ts +8 -11
  355. package/src/template/implementations/entity.template.ts +6 -6
  356. package/src/template/implementations/generated.template.ts +99 -99
  357. package/src/template/implementations/generated_http.template.ts +21 -54
  358. package/src/template/implementations/generated_sso.template.ts +78 -65
  359. package/src/template/implementations/init_types.template.ts +4 -6
  360. package/src/template/implementations/model.template.ts +47 -38
  361. package/src/template/implementations/model_test.template.ts +3 -3
  362. package/src/template/implementations/service.template.ts +56 -80
  363. package/src/template/implementations/view_enums_buttonset.template.ts +2 -2
  364. package/src/template/implementations/view_enums_dropdown.template.ts +4 -4
  365. package/src/template/implementations/view_enums_select.template.ts +3 -3
  366. package/src/template/implementations/view_form.template.ts +34 -75
  367. package/src/template/implementations/view_id_all_select.template.ts +2 -2
  368. package/src/template/implementations/view_id_async_select.template.ts +9 -23
  369. package/src/template/implementations/view_list.template.ts +54 -95
  370. package/src/template/implementations/view_list_columns.template.ts +4 -10
  371. package/src/template/implementations/view_search_input.template.ts +2 -2
  372. package/src/template/index.ts +4 -2
  373. package/src/template/template-manager.ts +166 -0
  374. package/src/template/template-types.ts +16 -0
  375. package/src/template/template.ts +29 -10
  376. package/src/template/zod-converter.ts +407 -101
  377. package/src/testing/_relation-graph.ts +18 -11
  378. package/src/testing/fixture-manager.ts +468 -362
  379. package/src/types/types.ts +516 -248
  380. package/src/typings/knex.d.ts +7 -9
  381. package/src/utils/async-utils.ts +8 -12
  382. package/src/utils/console-util.ts +1 -1
  383. package/src/utils/controller.ts +3 -0
  384. package/src/utils/esm-utils.ts +8 -18
  385. package/src/utils/formatter.ts +109 -0
  386. package/src/utils/fs-utils.ts +1 -1
  387. package/src/utils/lodash-able.ts +1 -4
  388. package/src/utils/object-utils.ts +217 -0
  389. package/src/utils/path-utils.ts +3 -6
  390. package/src/utils/process-utils.ts +1 -1
  391. package/src/utils/sql-parser.ts +23 -5
  392. package/src/utils/type-utils.ts +83 -0
  393. package/src/utils/utils.ts +58 -9
  394. package/src/utils/zod-error.ts +3 -3
  395. package/dist/bin/cli-wrapper.d.ts +0 -3
  396. package/dist/bin/cli-wrapper.d.ts.map +0 -1
  397. package/dist/bin/cli-wrapper.js +0 -72
  398. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts +0 -2
  399. package/dist/database/knex-plugins/knex-on-duplicate-update.d.ts.map +0 -1
  400. package/dist/database/knex-plugins/knex-on-duplicate-update.js +0 -39
  401. package/dist/entity/entity-utils.d.ts +0 -61
  402. package/dist/entity/entity-utils.d.ts.map +0 -1
  403. package/dist/entity/entity-utils.js +0 -210
  404. package/src/bin/cli-wrapper.ts +0 -82
  405. package/src/database/knex-plugins/knex-on-duplicate-update.ts +0 -45
  406. package/src/entity/entity-utils.ts +0 -291
@@ -1,34 +1,38 @@
1
+ /** biome-ignore-all lint/suspicious/noThenProperty: Puri는 thenable 인터페이스를 구현하고 있습니다. */
2
+ /** biome-ignore-all lint/suspicious/noExplicitAny: Puri는 다양한 타입을 사용하고 있습니다. */
3
+
4
+ import assert from "assert";
5
+ import chalk from "chalk";
1
6
  import type { Knex } from "knex";
7
+ import { Naite } from "../naite/naite";
2
8
  import type {
3
9
  AvailableColumns,
4
- SelectObject,
5
- ParseSelectObject,
6
- WhereCondition,
10
+ ColumnKeys,
7
11
  ComparisonOperator,
8
- ExtractColumnType,
9
- SqlExpression,
10
12
  Expand,
13
+ ExtractColumnType,
11
14
  FulltextColumns,
12
- ResultAvailableColumns,
13
15
  InsertData,
16
+ InsertResult,
17
+ OnConflictAction,
18
+ ParseSelectObject,
19
+ ResultAvailableColumns,
20
+ SelectObject,
14
21
  SingleTableValue,
22
+ SqlExpression,
23
+ WhereCondition,
15
24
  } from "./puri.types";
16
- import chalk from "chalk";
17
- import assert from "assert";
18
- import { Naite } from "../naite/naite";
25
+ import type { ClearStatements } from "./puri-subset.types";
19
26
 
20
27
  export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
21
28
  private knexQuery: Knex.QueryBuilder;
22
29
 
23
30
  // 생성자 시그니처들
24
31
  constructor(knex: Knex, tableName: string);
25
- constructor(
26
- knex: Knex,
27
- tableSpec: Record<string, string | Puri<TSchema, any, any>>
28
- );
32
+ constructor(knex: Knex, tableSpec: Record<string, string | Puri<TSchema, any, any>>);
29
33
  constructor(
30
34
  public knex: Knex,
31
- tableNameOrSpec: any
35
+ tableNameOrSpec: any,
32
36
  ) {
33
37
  if (typeof tableNameOrSpec === "string") {
34
38
  // Case: new Puri(knex, "users")
@@ -58,7 +62,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
58
62
  return {
59
63
  _type: "sql_expression",
60
64
  _return: "number",
61
- _sql: `COUNT(${column})`,
65
+ _sql: `COUNT(${column})::integer`,
62
66
  };
63
67
  }
64
68
  static sum(column: string): SqlExpression<"number"> {
@@ -127,19 +131,14 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
127
131
 
128
132
  // SELECT (overwrite)
129
133
  select<TSelect extends SelectObject<TTables>>(
130
- selectObj: TSelect
134
+ selectObj: TSelect,
131
135
  ): Puri<TSchema, TTables, ParseSelectObject<TTables, TSelect>> {
132
136
  const selectClauses: (string | Knex.Raw)[] = [];
133
137
 
134
138
  for (const [alias, columnOrFunction] of Object.entries(selectObj)) {
135
- if (
136
- typeof columnOrFunction === "object" &&
137
- columnOrFunction._type === "sql_expression"
138
- ) {
139
+ if (typeof columnOrFunction === "object" && columnOrFunction._type === "sql_expression") {
139
140
  // SQL 함수인 경우
140
- selectClauses.push(
141
- this.knex.raw(`${columnOrFunction._sql} as ${alias}`)
142
- );
141
+ selectClauses.push(this.knex.raw(`${columnOrFunction._sql} as ${alias}`));
143
142
  } else {
144
143
  // 일반 컬럼인 경우
145
144
  const columnPath = columnOrFunction as string;
@@ -159,7 +158,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
159
158
 
160
159
  // SELECT (select는 overwrite, appendSelect는 append)
161
160
  appendSelect<TSelect extends SelectObject<TTables>>(
162
- selectObj: TSelect
161
+ selectObj: TSelect,
163
162
  ): Puri<TSchema, TTables, TResult & ParseSelectObject<TTables, TSelect>> {
164
163
  return this.select(selectObj) as any;
165
164
  }
@@ -170,11 +169,30 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
170
169
  return this as any;
171
170
  }
172
171
 
172
+ // CLEAR
173
+ clear(statement: ClearStatements): this {
174
+ this.knexQuery.clear(statement);
175
+ return this;
176
+ }
177
+
178
+ // knex에 없어서 직접 구현함
179
+ clearJoin(alias: string): this {
180
+ (this.knexQuery as any)._statements = (this.knexQuery as any)._statements.filter((s: any) => {
181
+ if ("joinType" in s) {
182
+ const [_alias, _table] = Object.entries(s.table)[0];
183
+ return _alias !== alias;
184
+ } else {
185
+ return true;
186
+ }
187
+ });
188
+ return this;
189
+ }
190
+
173
191
  // JOIN: 서브쿼리 + Alias
174
192
  join<TJoinAlias extends string, TSubResult>(
175
193
  tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
176
194
  left: AvailableColumns<TTables>,
177
- right: `${TJoinAlias}.${keyof TSubResult & string}`
195
+ right: `${TJoinAlias}.${ColumnKeys<TSubResult>}`,
178
196
  ): Puri<
179
197
  TSchema,
180
198
  TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult
@@ -184,7 +202,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
184
202
  join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
185
203
  tableSpec: { [K in TJoinAlias]: TJoinTable },
186
204
  left: AvailableColumns<TTables>,
187
- right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`
205
+ right: `${TJoinAlias}.${ColumnKeys<TSchema[TJoinTable]>}`,
188
206
  ): Puri<
189
207
  TSchema,
190
208
  TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!
@@ -194,7 +212,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
194
212
  join<TJoinTable extends keyof TSchema>(
195
213
  tableName: TJoinTable,
196
214
  left: AvailableColumns<TTables>,
197
- right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`
215
+ right: `${TJoinTable & string}.${ColumnKeys<TSchema[TJoinTable]>}`,
198
216
  ): Puri<
199
217
  TSchema,
200
218
  TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키
@@ -203,23 +221,17 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
203
221
  // JOIN: 서브쿼리 + Alias + 콜백
204
222
  join<TJoinAlias extends string, TSubResult>(
205
223
  tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
206
- callback: (
207
- j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>
208
- ) => void
224
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>) => void,
209
225
  ): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;
210
226
  // JOIN: 테이블 + Alias + 콜백
211
227
  join<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
212
228
  tableSpec: { [K in TJoinAlias]: TJoinTable },
213
- callback: (
214
- j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>
215
- ) => void
229
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>) => void,
216
230
  ): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;
217
231
  // JOIN: 테이블명 + 콜백
218
232
  join<TJoinTable extends keyof TSchema>(
219
233
  tableName: TJoinTable,
220
- callback: (
221
- j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>
222
- ) => void
234
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>) => void,
223
235
  ): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;
224
236
  // JOIN 실제 구현
225
237
  join(tableNameOrSpec: any, ...args: any[]): any {
@@ -230,7 +242,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
230
242
  leftJoin<TJoinAlias extends string, TSubResult>(
231
243
  tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
232
244
  left: AvailableColumns<TTables>,
233
- right: `${TJoinAlias}.${keyof TSubResult & string}`
245
+ right: `${TJoinAlias}.${ColumnKeys<TSubResult>}`,
234
246
  ): Puri<
235
247
  TSchema,
236
248
  TTables & Record<TJoinAlias, TSubResult>, // 서브쿼리의 TResult
@@ -240,7 +252,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
240
252
  leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
241
253
  tableSpec: { [K in TJoinAlias]: TJoinTable },
242
254
  left: AvailableColumns<TTables>,
243
- right: `${TJoinAlias}.${keyof TSchema[TJoinTable] & string}`
255
+ right: `${TJoinAlias}.${ColumnKeys<TSchema[TJoinTable]>}`,
244
256
  ): Puri<
245
257
  TSchema,
246
258
  TTables & Record<TJoinAlias, TSchema[TJoinTable]>, // TTables 확장!
@@ -250,7 +262,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
250
262
  leftJoin<TJoinTable extends keyof TSchema>(
251
263
  tableName: TJoinTable,
252
264
  left: AvailableColumns<TTables>,
253
- right: `${TJoinTable & string}.${keyof TSchema[TJoinTable] & string}`
265
+ right: `${TJoinTable & string}.${ColumnKeys<TSchema[TJoinTable]>}`,
254
266
  ): Puri<
255
267
  TSchema,
256
268
  TTables & Record<TJoinTable, TSchema[TJoinTable]>, // 테이블명이 키
@@ -259,34 +271,24 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
259
271
  // LEFT JOIN: 서브쿼리 + Alias + 콜백
260
272
  leftJoin<TJoinAlias extends string, TSubResult>(
261
273
  tableSpec: { [K in TJoinAlias]: Puri<TSchema, any, TSubResult> },
262
- callback: (
263
- j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>
264
- ) => void
274
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinAlias, TSubResult>>) => void,
265
275
  ): Puri<TSchema, TTables & Record<TJoinAlias, TSubResult>, TResult>;
266
276
  // LEFT JOIN: 테이블 + Alias + 콜백
267
277
  leftJoin<TJoinTable extends keyof TSchema, TJoinAlias extends string>(
268
278
  tableSpec: { [K in TJoinAlias]: TJoinTable },
269
- callback: (
270
- j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>
271
- ) => void
279
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinAlias, TSchema[TJoinTable]>>) => void,
272
280
  ): Puri<TSchema, TTables & Record<TJoinAlias, TSchema[TJoinTable]>, TResult>;
273
281
  // LEFT JOIN: 테이블명 + 콜백
274
282
  leftJoin<TJoinTable extends keyof TSchema>(
275
283
  tableName: TJoinTable,
276
- callback: (
277
- j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>
278
- ) => void
284
+ callback: (j: JoinClauseGroup<TTables, Record<TJoinTable, TSchema[TJoinTable]>>) => void,
279
285
  ): Puri<TSchema, TTables & Record<TJoinTable, TSchema[TJoinTable]>, TResult>;
280
286
  // LEFT JOIN 실제 구현
281
287
  leftJoin(tableNameOrSpec: any, ...args: any[]): any {
282
288
  return this.__commonJoin("leftJoin", tableNameOrSpec, ...args);
283
289
  }
284
290
 
285
- __commonJoin(
286
- joinType: "join" | "leftJoin",
287
- tableNameOrSpec: any,
288
- ...args: any[]
289
- ): this {
291
+ __commonJoin(joinType: "join" | "leftJoin", tableNameOrSpec: any, ...args: any[]): this {
290
292
  if (typeof tableNameOrSpec === "string") {
291
293
  // Case 1: join("posts", ...)
292
294
  const tableName = tableNameOrSpec;
@@ -352,25 +354,26 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
352
354
  // WHERE: 컬럼 - 사용: .where("u.id", 1)
353
355
  where<TColumn extends AvailableColumns<TTables>>(
354
356
  column: TColumn,
355
- value: ExtractColumnType<TTables, TColumn & string>
357
+ value: ExtractColumnType<TTables, TColumn & string>,
356
358
  ): this;
357
359
  // WHERE: 컬럼 - 사용: .where("u.id", ">", 10)
358
360
  where<TColumn extends AvailableColumns<TTables>>(
359
361
  column: TColumn,
360
362
  operator: ComparisonOperator | "like" | "not like",
361
- value: ExtractColumnType<TTables, TColumn & string>
363
+ value: ExtractColumnType<TTables, TColumn & string>,
362
364
  ): this;
363
365
  // WHERE: 컬럼 - 사용: .where("u.id", "like", "%test%")
364
- where(columnOrConditions: any, operatorOrValue?: any, value?: any): this {
366
+ where(...args: [columnOrConditions: any, operatorOrValue?: any, value?: any]): this {
367
+ const [columnOrConditions, operatorOrValue, value] = args;
365
368
  if (typeof columnOrConditions === "object") {
366
369
  this.knexQuery.where(columnOrConditions);
367
- } else if (arguments.length === 2) {
370
+ } else if (typeof value === "undefined") {
368
371
  if (operatorOrValue === null) {
369
372
  this.knexQuery.whereNull(columnOrConditions);
370
373
  return this;
371
374
  }
372
375
  this.knexQuery.where(columnOrConditions, operatorOrValue);
373
- } else if (arguments.length === 3) {
376
+ } else if (typeof value !== "undefined") {
374
377
  if (value === null) {
375
378
  if (operatorOrValue === "!=") {
376
379
  this.knexQuery.whereNotNull(columnOrConditions);
@@ -390,7 +393,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
390
393
  // WHERE IN
391
394
  whereIn<TColumn extends AvailableColumns<TTables>>(
392
395
  column: TColumn,
393
- values: ExtractColumnType<TTables, TColumn & string>[]
396
+ values: ExtractColumnType<TTables, TColumn & string>[],
394
397
  ): Puri<TSchema, TTables, TResult> {
395
398
  this.knexQuery.whereIn(column, values);
396
399
  return this as any;
@@ -399,17 +402,14 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
399
402
  // WHERE NOT IN
400
403
  whereNotIn<TColumn extends AvailableColumns<TTables>>(
401
404
  column: TColumn,
402
- values: ExtractColumnType<TTables, TColumn & string>[]
405
+ values: ExtractColumnType<TTables, TColumn & string>[],
403
406
  ): Puri<TSchema, TTables, TResult> {
404
- this.knexQuery.whereIn(column, values);
407
+ this.knexQuery.whereNotIn(column, values);
405
408
  return this as any;
406
409
  }
407
410
 
408
411
  // WHERE MATCH
409
- whereMatch<TColumn extends FulltextColumns<TTables>>(
410
- column: TColumn,
411
- value: string
412
- ): this {
412
+ whereMatch<TColumn extends FulltextColumns<TTables>>(column: TColumn, value: string): this {
413
413
  this.knexQuery.whereRaw(`MATCH (${String(column)}) AGAINST (?)`, [value]);
414
414
  return this;
415
415
  }
@@ -433,7 +433,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
433
433
  // ORDER BY
434
434
  orderBy<TColumn extends ResultAvailableColumns<TTables, TResult>>(
435
435
  column: TColumn,
436
- direction: "asc" | "desc"
436
+ direction: "asc" | "desc",
437
437
  ): this;
438
438
  orderBy(column: string, direction: "asc" | "desc" = "asc"): this {
439
439
  this.knexQuery.orderBy(column, direction);
@@ -452,9 +452,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
452
452
  }
453
453
 
454
454
  // GROUP BY
455
- groupBy<TColumns extends ResultAvailableColumns<TTables, TResult>>(
456
- ...columns: TColumns[]
457
- ): this;
455
+ groupBy<TColumns extends ResultAvailableColumns<TTables, TResult>>(...columns: TColumns[]): this;
458
456
  groupBy(...columns: string[]): this {
459
457
  this.knexQuery.groupBy(...(columns as string[]));
460
458
  return this;
@@ -465,16 +463,20 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
465
463
  having<TColumn extends ResultAvailableColumns<TTables, TResult>>(
466
464
  column: TColumn,
467
465
  operator: ComparisonOperator,
468
- value: any
466
+ value: any,
469
467
  ): this;
470
468
  // HAVING 구현
471
469
  having(...conditions: any[]): this {
472
470
  if (conditions.length === 1) {
473
471
  // having("COUNT(*) > 10")
474
- this.knexQuery.having(conditions[0]);
472
+ this.knexQuery.having(this.knex.raw(conditions[0]));
475
473
  } else if (conditions.length === 3) {
476
474
  // having("count", ">", 10)
477
- this.knexQuery.having(conditions[0], conditions[1], conditions[2]);
475
+ this.knexQuery.having(
476
+ this.knex.raw(conditions[0]),
477
+ conditions[1],
478
+ this.knex.raw(conditions[2]),
479
+ );
478
480
  } else {
479
481
  throw new Error("Invalid having arguments");
480
482
  }
@@ -483,16 +485,14 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
483
485
 
484
486
  // 실행 메서드들 - thenable 구현
485
487
  then<TResult1 = Expand<TResult>[], TResult2 = never>(
486
- onfulfilled?:
487
- | ((value: Expand<TResult>[]) => TResult1 | PromiseLike<TResult1>)
488
- | null,
489
- onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
488
+ onfulfilled?: ((value: Expand<TResult>[]) => TResult1 | PromiseLike<TResult1>) | null,
489
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
490
490
  ): Promise<TResult1 | TResult2> {
491
- Naite.t("puri-query", this.toQuery());
491
+ Naite.t("puri:executed-query", this.toQuery());
492
492
  return this.knexQuery.then(onfulfilled as any, onrejected);
493
493
  }
494
494
  catch<TResult2 = never>(
495
- onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
495
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
496
496
  ): Promise<TResult | TResult2> {
497
497
  return this.knexQuery.catch(onrejected);
498
498
  }
@@ -503,14 +503,12 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
503
503
  // 하나만 쿼리
504
504
  first(): ResolvedPuri<Expand<TResult>, never> {
505
505
  this.knexQuery.first();
506
- return new ResolvedPuri(this.knexQuery);
506
+ return new ResolvedPuri(this.knexQuery, this.knex);
507
507
  }
508
508
 
509
509
  // 쿼리한 레코드에서 특정 컬럼만 추출한 배열 리턴
510
- pluck<
511
- TColumn extends keyof TResult | ResultAvailableColumns<TTables, TResult>,
512
- >(
513
- column: TColumn
510
+ pluck<TColumn extends keyof TResult | ResultAvailableColumns<TTables, TResult>>(
511
+ column: TColumn,
514
512
  ): ResolvedPuri<
515
513
  TColumn extends keyof TResult
516
514
  ? TResult[TColumn][]
@@ -518,50 +516,50 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
518
516
  never
519
517
  > {
520
518
  this.knexQuery.pluck(column as string);
521
- return new ResolvedPuri(this.knexQuery);
519
+ return new ResolvedPuri(this.knexQuery, this.knex);
522
520
  }
523
521
 
524
522
  // INSERT
525
523
  insert(
526
- data: InsertData<SingleTableValue<TTables>>
527
- ): ResolvedPuri<[number], never> {
524
+ data: InsertData<SingleTableValue<TTables>>,
525
+ ): ResolvedPuri<InsertResult, SingleTableValue<TTables>> {
528
526
  this.knexQuery.insert(data);
529
- return new ResolvedPuri(this.knexQuery);
527
+ return new ResolvedPuri(this.knexQuery, this.knex);
530
528
  }
531
529
 
532
530
  // UPDATE
533
- update(data: WhereCondition<TTables>): ResolvedPuri<TResult, number> {
531
+ update(data: WhereCondition<TTables>): ResolvedPuri<number, SingleTableValue<TTables>> {
534
532
  this.knexQuery.update(data);
535
- return new ResolvedPuri(this.knexQuery);
533
+ return new ResolvedPuri(this.knexQuery, this.knex);
536
534
  }
537
535
 
538
536
  // Increment
539
537
  increment<TColumn extends AvailableColumns<TTables>>(
540
538
  column: TColumn,
541
- value: number
542
- ): ResolvedPuri<number, never> {
539
+ value: number,
540
+ ): ResolvedPuri<number, SingleTableValue<TTables>> {
543
541
  if (value <= 0) {
544
542
  throw new Error("Increment value must be greater than 0");
545
543
  }
546
544
  this.knexQuery.increment(column, value);
547
- return new ResolvedPuri(this.knexQuery);
545
+ return new ResolvedPuri(this.knexQuery, this.knex);
548
546
  }
549
547
  // Decrement
550
548
  decrement<TColumn extends AvailableColumns<TTables>>(
551
549
  column: TColumn,
552
- value: number
553
- ): ResolvedPuri<number, never> {
550
+ value: number,
551
+ ): ResolvedPuri<number, SingleTableValue<TTables>> {
554
552
  if (value <= 0) {
555
553
  throw new Error("Decrement value must be greater than 0");
556
554
  }
557
555
  this.knexQuery.decrement(column, value);
558
- return new ResolvedPuri(this.knexQuery);
556
+ return new ResolvedPuri(this.knexQuery, this.knex);
559
557
  }
560
558
 
561
559
  // DELETE
562
- delete(): ResolvedPuri<number, never> {
560
+ delete(): ResolvedPuri<number, SingleTableValue<TTables>> {
563
561
  this.knexQuery.delete();
564
- return new ResolvedPuri(this.knexQuery);
562
+ return new ResolvedPuri(this.knexQuery, this.knex);
565
563
  }
566
564
 
567
565
  // 확인 쿼리 리턴
@@ -571,12 +569,17 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
571
569
 
572
570
  // 쿼리 디버깅 로그 출력
573
571
  debug(): this {
574
- console.log(
575
- `${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`
576
- );
572
+ console.log(`${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`);
577
573
  return this;
578
574
  }
579
575
 
576
+ clone(): Puri<TSchema, TTables, TResult> {
577
+ // 'dual'은 더미 테이블이며, 바로 아래 줄에서 knexQuery가 덮어씌워집니다.
578
+ const newPuri = new Puri<TSchema, TTables, TResult>(this.knex, "dual");
579
+ newPuri.knexQuery = this.knexQuery.clone();
580
+ return newPuri;
581
+ }
582
+
580
583
  formatSQL(unformatted: string): string {
581
584
  // SQL 예약어 목록
582
585
  const keywords = [
@@ -650,10 +653,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
650
653
  });
651
654
 
652
655
  // JOIN 절 처리
653
- formatted = formatted.replace(
654
- /\s+((?:INNER|LEFT|RIGHT|FULL OUTER)\s+)?JOIN\s+/gi,
655
- "\n$1JOIN "
656
- );
656
+ formatted = formatted.replace(/\s+((?:INNER|LEFT|RIGHT|FULL OUTER)\s+)?JOIN\s+/gi, "\n$1JOIN ");
657
657
 
658
658
  // AND, OR 조건 처리
659
659
  formatted = formatted.replace(/\s+(AND|OR)\s+/gi, "\n $1 ");
@@ -663,7 +663,7 @@ export class Puri<TSchema, TTables extends Record<string, any>, TResult> {
663
663
  const indentedLines = [];
664
664
  let indentLevel = 0;
665
665
 
666
- for (let line of lines) {
666
+ for (const line of lines) {
667
667
  const trimmedLine = line.trim();
668
668
  if (!trimmedLine) continue;
669
669
 
@@ -701,12 +701,12 @@ export class WhereGroup<TTables extends Record<string, any>> {
701
701
  where(conditions: WhereCondition<TTables>): this;
702
702
  where<TColumn extends AvailableColumns<TTables>>(
703
703
  column: TColumn,
704
- value: ExtractColumnType<TTables, TColumn & string>
704
+ value: ExtractColumnType<TTables, TColumn & string>,
705
705
  ): this;
706
706
  where<TColumn extends AvailableColumns<TTables>>(
707
707
  column: TColumn,
708
708
  operator: ComparisonOperator,
709
- value: ExtractColumnType<TTables, TColumn & string>
709
+ value: ExtractColumnType<TTables, TColumn & string>,
710
710
  ): this;
711
711
  where(...args: any[]): WhereGroup<TTables> {
712
712
  this.builder.where(args[0], ...args.slice(1));
@@ -717,12 +717,12 @@ export class WhereGroup<TTables extends Record<string, any>> {
717
717
  orWhere(conditions: WhereCondition<TTables>): this;
718
718
  orWhere<TColumn extends AvailableColumns<TTables>>(
719
719
  column: TColumn,
720
- value: ExtractColumnType<TTables, TColumn & string>
720
+ value: ExtractColumnType<TTables, TColumn & string>,
721
721
  ): this;
722
722
  orWhere<TColumn extends AvailableColumns<TTables>>(
723
723
  column: TColumn,
724
724
  operator: ComparisonOperator,
725
- value: ExtractColumnType<TTables, TColumn & string>
725
+ value: ExtractColumnType<TTables, TColumn & string>,
726
726
  ): this;
727
727
  orWhere(...args: any[]): WhereGroup<TTables> {
728
728
  this.builder.orWhere(args[0], ...args.slice(1));
@@ -739,9 +739,7 @@ export class WhereGroup<TTables extends Record<string, any>> {
739
739
  return this;
740
740
  }
741
741
  orWhereGroup(callback: (g: WhereGroup<TTables>) => void): this;
742
- orWhereGroup(
743
- callback: (g: WhereGroup<TTables>) => void
744
- ): WhereGroup<TTables> {
742
+ orWhereGroup(callback: (g: WhereGroup<TTables>) => void): WhereGroup<TTables> {
745
743
  this.builder.orWhere((subBuilder) => {
746
744
  const subGroup = new WhereGroup<TTables>(subBuilder);
747
745
  callback(subGroup);
@@ -762,7 +760,7 @@ export class JoinClauseGroup<
762
760
  on(
763
761
  left: AvailableColumns<TLeft>,
764
762
  operator: ComparisonOperator,
765
- right: AvailableColumns<TRight>
763
+ right: AvailableColumns<TRight>,
766
764
  ): this;
767
765
  // ON(AND): 콜백
768
766
  on(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;
@@ -778,7 +776,7 @@ export class JoinClauseGroup<
778
776
  orOn(
779
777
  left: AvailableColumns<TLeft>,
780
778
  operator: ComparisonOperator,
781
- right: AvailableColumns<TRight>
779
+ right: AvailableColumns<TRight>,
782
780
  ): this;
783
781
  // ON(OR): 콜백
784
782
  orOn(callback: (nested: JoinClauseGroup<TLeft, TRight>) => void): this;
@@ -791,37 +789,95 @@ export class JoinClauseGroup<
791
789
 
792
790
  /*
793
791
  TResolved: 쿼리 실행 후 반환될 결과 타입
794
- _TReturning: 추후 RETURNING 절에 사용될 타입
792
+ TReturning: RETURNING 절에 사용될 타입
795
793
  */
796
- export class ResolvedPuri<TResolved, _TReturning> {
797
- constructor(public knexQuery: Knex.QueryBuilder) {}
794
+ export class ResolvedPuri<TResolved, TReturning> {
795
+ constructor(
796
+ public knexQuery: Knex.QueryBuilder,
797
+ private knex: Knex,
798
+ ) {}
798
799
 
799
800
  toQuery(): string {
800
801
  return this.knexQuery.toQuery();
801
802
  }
802
803
 
803
804
  debug(): this {
804
- console.log(
805
- `${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`
806
- );
805
+ console.log(`${chalk.cyan("[Puri Debug]")} ${chalk.yellow(this.toQuery())}`);
807
806
  return this;
808
807
  }
809
808
 
810
809
  then<TResult1 = TResolved, TResult2 = never>(
811
- onfulfilled?:
812
- | ((value: TResolved) => TResult1 | PromiseLike<TResult1>)
813
- | null,
814
- onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
810
+ onfulfilled?: ((value: TResolved) => TResult1 | PromiseLike<TResult1>) | null,
811
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
815
812
  ): Promise<TResult1 | TResult2> {
816
- Naite.t("puri-query", this.toQuery());
813
+ Naite.t("puri:executed-query", this.toQuery());
817
814
  return this.knexQuery.then(onfulfilled as any, onrejected);
818
815
  }
819
816
  catch<TResult2 = never>(
820
- onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
817
+ onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
821
818
  ): Promise<TResolved | TResult2> {
822
819
  return this.knexQuery.catch(onrejected);
823
820
  }
824
821
  finally(onfinally?: (() => void) | null): Promise<TResolved> {
825
822
  return this.knexQuery.finally(onfinally);
826
823
  }
824
+
825
+ // ON CONFLICT - 컬럼 기반
826
+ onConflict<TTables extends Record<string, TReturning>>(
827
+ columns: string | string[],
828
+ action?: OnConflictAction<TTables>,
829
+ ): this {
830
+ const target = Array.isArray(columns) ? columns : [columns];
831
+
832
+ if (!action || action === "nothing") {
833
+ // DO NOTHING
834
+ this.knexQuery.onConflict(target).ignore();
835
+ } else {
836
+ // DO UPDATE
837
+ const { update } = action;
838
+
839
+ // action.update 배열 형태 : ["name", "email"]
840
+ if (Array.isArray(update)) {
841
+ this.knexQuery.onConflict(target).merge(update);
842
+ } else {
843
+ // action.update 객체 형태: { name: "John", count: raw(...) }
844
+ const mergeObj: Record<string, any> = {};
845
+
846
+ for (const [key, value] of Object.entries(update)) {
847
+ if (
848
+ value &&
849
+ typeof value === "object" &&
850
+ "_type" in value &&
851
+ value._type === "sql_expression"
852
+ ) {
853
+ // SqlExpression → knex.raw()로 변환
854
+ mergeObj[key] = this.knex.raw((value as SqlExpression<any>)._sql);
855
+ } else {
856
+ // 일반 값
857
+ mergeObj[key] = value;
858
+ }
859
+ }
860
+
861
+ this.knexQuery.onConflict(target).merge(mergeObj);
862
+ }
863
+ }
864
+
865
+ return this;
866
+ }
867
+
868
+ // RETURNING: "*" - 전체 컬럼
869
+ returning(column: "*"): ResolvedPuri<TReturning[], never>;
870
+ // RETURNING: 단일 컬럼
871
+ returning<TColumn extends ColumnKeys<TReturning>>(
872
+ column: TColumn,
873
+ ): ResolvedPuri<Pick<TReturning, TColumn>[], never>;
874
+ // RETURNING: 복수 컬럼 (배열)
875
+ returning<TColumn extends ColumnKeys<TReturning>>(
876
+ columns: TColumn[],
877
+ ): ResolvedPuri<Pick<TReturning, TColumn>[], never>;
878
+ // RETURNING 구현
879
+ returning(columnOrColumns: string | string[]): ResolvedPuri<any[], never> {
880
+ this.knexQuery.returning(columnOrColumns);
881
+ return new ResolvedPuri(this.knexQuery, this.knex);
882
+ }
827
883
  }